(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: https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/socket/message.ex 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:

1 Like

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:

https://hexdocs.pm/iex/IEx.Pry.html#break/4

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

1 Like