When using associated schemas with live view the token verification fails if the session includes a changeset that was created with cast_assoc. Leaving out cast_assoc gets rid of the error but doesn't give the correct functionality.
[error] GenServer #PID<0.469.0> terminating
** (ArgumentError) cannot deserialize #Function<15.34706895/2 in Ecto.Changeset.on_cast_default/2>, the term is not safe for deserialization
(plug_crypto) lib/plug/crypto.ex:59: Plug.Crypto.safe_terms/1
(plug_crypto) lib/plug/crypto.ex:45: anonymous fn/3 in Plug.Crypto.safe_terms/1
(stdlib) maps.erl:257: :maps.fold_1/3
(plug_crypto) lib/plug/crypto.ex:78: Plug.Crypto.safe_tuple/2
(plug_crypto) lib/plug/crypto.ex:45: anonymous fn/3 in Plug.Crypto.safe_terms/1
(stdlib) maps.erl:257: :maps.fold_1/3
(plug_crypto) lib/plug/crypto.ex:45: anonymous fn/3 in Plug.Crypto.safe_terms/1
(stdlib) maps.erl:257: :maps.fold_1/3
(plug_crypto) lib/plug/crypto.ex:45: anonymous fn/3 in Plug.Crypto.safe_terms/1
(stdlib) maps.erl:257: :maps.fold_1/3
(plug_crypto) lib/plug/crypto.ex:45: anonymous fn/3 in Plug.Crypto.safe_terms/1
(stdlib) maps.erl:257: :maps.fold_1/3
(plug_crypto) lib/plug/crypto.ex:45: anonymous fn/3 in Plug.Crypto.safe_terms/1
(stdlib) maps.erl:257: :maps.fold_1/3
(plug_crypto) lib/plug/crypto.ex:30: Plug.Crypto.safe_binary_to_term/2
(phoenix) lib/phoenix/token.ex:177: Phoenix.Token.verify/4
(phoenix_live_view) lib/phoenix_live_view/view.ex:155: Phoenix.LiveView.View.verify_token/2
(phoenix_live_view) lib/phoenix_live_view/view.ex:146: Phoenix.LiveView.View.verify_session/3
(phoenix_live_view) lib/phoenix_live_view/channel.ex:221: Phoenix.LiveView.Channel.mount/1
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
Last message: {:mount, Phoenix.LiveView.Channel}
I've created a simple application that reproduces the error here https://github.com/adamvaughan/testapp. Create/migrate the database, boot the server and visit the root path and you should see the error immediately.
Token verification works without raising an error.
So the issue is that you are trying to serialize data that cannot be serialized (i.e. it contains functions). You are supposed to put in the session the information necessary to retrieve the data, not the data itself. For example, instead of putting the user struct from Ecto in the session, put the user id and query it when live view starts.
I'm getting a similar issue with #Function<0.76412652/1 in Plug.CSRFProtection.call/2>. What could be the issue there?
It depends on what you are storing in your session. It seems you are trying to store the whole Plug.Conn. You should only store integer, strings, and so on.
Thanks for the clarification @josevalim! Switching to storing integers in the session and assigning other objects I wanted to have kept in state to the socket resolved this issue for me.
I would like to use route helpers in my LiveView template, but I can't assign the conn to the socket without getting the same error as above. I think am misssing something...
` def mount(%{conn: conn, ranking: ranking}, socket) do
weights = get_session_weights(ranking)
fset = ranking.filter
results = Rankings.get_ranked_results(fset, weights)
openResults = set_open_results(results)
socket =
socket
#|> assign(conn: conn) # Uncommenting this line will cause error
|> assign(ranking: ranking)
|> assign(fset: fset)
|> assign(results: results)
|> assign(score_weights: weights)
|> assign(openFilters: MapSet.new([:stroke]))
|> assign(openResults: openResults)
|> assign(openScoreWeights: false)
{:ok, socket}
end`
@jamilabreu Have you tried build the route path using the socket instead? I believe it should work 馃
Routes.user_path(socket, :index)
Yes, socket works fine. Thank you.
Most helpful comment
It depends on what you are storing in your session. It seems you are trying to store the whole
Plug.Conn. You should only store integer, strings, and so on.