(Phoenix.Socket.InvalidMessageError) missing key "topic"

Can someone explain why I get this error:

11:50:00.789 [error] Ranch protocol #PID<0.655.0> (:cowboy_protocol) of listener MyApp.Schools.Endpoint.HTTP terminated
** (exit) exited in: Phoenix.Endpoint.CowboyWebSocket.resume()
    ** (EXIT) an exception was raised:
        ** (Phoenix.Socket.InvalidMessageError) missing key "topic"
            (phoenix) lib/phoenix/socket/message.ex:32: Phoenix.Socket.Message.from_map!/1
            (phoenix) lib/phoenix/transports/websocket.ex:106: Phoenix.Transports.WebSocket.ws_handle/3
            (phoenix) lib/phoenix/endpoint/cowboy_websocket.ex:77: Phoenix.Endpoint.CowboyWebSocket.websocket_handle/3
            (cowboy) /Users/samir/Documents/projects/elixir/deps/cowboy/src/cowboy_websocket.erl:588: :cowboy_websocket.handler_call/7
            (phoenix) lib/phoenix/endpoint/cowboy_websocket.ex:49: Phoenix.Endpoint.CowboyWebSocket.resume/3
            (cowboy) /Users/samir/Documents/projects/elixir/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

If you take a look at: phoenix/lib/phoenix/socket/message.ex at main · phoenixframework/phoenix · GitHub around line 32 (as pointed to in the error) we see this:

  def from_map!(map) when is_map(map) do
    try do
      %Phoenix.Socket.Message{
        topic: Map.fetch!(map, "topic"),
        event: Map.fetch!(map, "event"),
        payload: Map.fetch!(map, "payload"),
        ref: Map.fetch!(map, "ref"),
        join_ref: Map.get(map, "join_ref"),
      }
    rescue
      err in [KeyError] ->
        raise Phoenix.Socket.InvalidMessageError, "missing key #{inspect err.key}"
    end
  end
end

Ok, so it is failing to get a key with Map.fetch! .. and the error tells us which one: topic. So every message you send needs to contain the topic it relates to.

This is usually accomplished on the client side by using channel.push(), where channel comes from socket.channel(topic, params) .. if the channel is not given a topic, if the message is being sent “manually” across the socket, or is being formulated incorrectly by the underlying library in use, then you can end up without a topic key and things will go boom if a message is sent to the socket without that data …

.. so, hard to say without seeing the client side code, but hopefully that gets you started? :slight_smile:

Thanks @aseigo, yes, at least I know that its a problem related to the client side, but, can’t I configure phoenix to tell more details about the error? like for example, what was the content of the message sent?

Yep, you can use IEx.Pry.break/4 as covered here:

You can put a breakpoint in that from_map! function and then see what the message is.