Phoenix Channels "phx_error" on the socket in CI
The Phoenix JS/socket protocol sends phx_error when a channel process crashes or the socket transport errors. Instead of a phx_reply with :ok, the client gets a phx_error and the channel is closed.
What this error means
A JS or integration test observes a phx_error message on the channel, or the server logs a channel crash. The channel that was joined stops responding.
[error] GenServer #PID<0.512.0> terminating
** (KeyError) key :user_id not found in: %{}
Last message: %Phoenix.Socket.Message{event: "phx_join", topic: "room:lobby", ...}
push("phx_error", %{})Common causes
The channel process crashed handling a message
An exception in a channel callback (a missing key, a failed match) terminates the channel process, and Phoenix emits phx_error to the client.
The socket transport errored
A transport-level failure on the socket surfaces to the client as phx_error, closing the affected channels.
How to fix it
Fix the crashing callback
- Read the server log line that precedes the phx_error to find the exception.
- Handle the missing key or failed match in the channel callback.
- Re-run the test and assert a
:okreply instead of an error.
def join("room:" <> _id, _params, socket) do
case socket.assigns[:user_id] do
nil -> {:error, %{reason: "unauthorized"}}
_ -> {:ok, socket}
end
endAssert the failure explicitly in tests
When an error is expected, assert on it so the test is deterministic.
assert {:error, %{reason: "unauthorized"}} =
subscribe_and_join(socket, "room:lobby", %{})How to prevent it
- Guard channel callbacks against missing assigns and bad params.
- Read the server crash log that precedes any phx_error.
- Assert expected error replies rather than treating them as flakes.