Channels Example from Docs Giving Strange Error

I was following the example from the phoenix docs for the channels and I get the following error when trying to broadcast to all connected channels:

[error] GenServer #PID<0.327.0> terminating
** (FunctionClauseError) no function clause matching in ChatAppWeb.RoomChannel.handle_in/3
    (chat_app) lib/chat_app_web/channels/room_channel.ex:8: 
    
    ChatAppWeb.RoomChannel.handle_in(   "new_msg", 
                                        %{"body" => "ddfdf"}, 
                                        %Phoenix.Socket{
                                            assigns: %{}, 
                                            channel: ChatAppWeb.RoomChannel, 
                                            channel_pid: #PID<0.327.0>, 
                                            endpoint: ChatAppWeb.Endpoint, 
                                            handler: ChatAppWeb.UserSocket, 
                                            id: nil, 
                                            join_ref: "9", 
                                            joined: true, 
                                            private: %{log_handle_in: :debug, log_join: :info}, 
                                            pubsub_server: ChatApp.PubSub, 
                                            ref: "10", 
                                            serializer: Phoenix.Transports.V2.WebSocketSerializer, 
                                            topic: "room:lobby", 
                                            transport: Phoenix.Transports.WebSocket, 
                                            transport_name: :websocket, 
                                            transport_pid: #PID<0.315.0>, vsn: "2.0.0"
                                            }
                                    )
    (phoenix) lib/phoenix/channel/server.ex:244: anonymous fn/4 in Phoenix.Channel.Server.handle_info/2
    (chat_app) lib/chat_app_web/endpoint.ex:1: ChatAppWeb.Endpoint.instrument/4
    (stdlib) gen_server.erl:601: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:667: :gen_server.handle_msg/5
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

 Last message: %Phoenix.Socket.Message{
                        event: "new_msg", 
                        join_ref: "9", 
                        payload: %{ "body" => "ddfdf"}, 
                        ref: "10", 
                        topic: "room:lobby"
                    }

State: %Phoenix.Socket{
                assigns: %{}, 
                channel: ChatAppWeb.RoomChannel, 
                channel_pid: #PID<0.327.0>, 
                endpoint: ChatAppWeb.Endpoint, 
                handler: ChatAppWeb.UserSocket, 
                id: nil, 
                join_ref: "9", 
                joined: true, 
                private: %{log_handle_in: :debug, log_join: :info}, 
                pubsub_server: ChatApp.PubSub, 
                ref: nil, 
                serializer: Phoenix.Transports.V2.WebSocketSerializer, 
                topic: "room:lobby", 
                transport: Phoenix.Transports.WebSocket, 
                transport_name: :websocket, 
                transport_pid: #PID<0.315.0>, 
                vsn: "2.0.0"
            }

Here is the code from my channel

defmodule ChatAppWeb.RoomChannel do 
    use Phoenix.Channel

    def join("room:lobby", _message, socket) do 
        {:ok, socket}
    end

    def handle_in("new_msg", params, socket) do 
        broadcast ! socket, "new_msg", %{body: "test_response"}
        {:noreply, socket}
    end

Any ideas as to why I am getting this error?

Thanks in advance
end

1 Like

Maybe here …

broadcast ! socket, “new_msg”, %{body: “test_response”}

But You test for

%{“body” => “ddfdf”}

and :body != “body” in your guard clause.

You can try to add a catch all handle_in and log the output, like this…

  def handle_in(command, payload, socket) do
    Logger.debug("unknown command #{command} with payload #{inspect payload}")
    {:noreply, socket}
  end
1 Like

As far as I can see, that should match.

Please delete your build folder and recompile your application to make sure the compiled module actually represents your sourcefile.

If it doesn’t work after that, there is probably some “invisible” character in the command string (either the one you use in your source or the one from the message).

In this case, please add a catch-all clause as suggested by @kokolegorille, but use this line to log:

Logger.debug("Unknown command '#{command}' (#{inspect command, base: :hex}) with payload #{inspect payload}")

This will also show a “raw” representation of the command to identify invisible characters.

2 Likes

This is unrelated. The error tells us about an incomming message that doesn’t find its clause, while the ! shall send a response to any message that is handled by this matching clause.

Which guard clause?

1 Like

This one, and it is pattern match, not guard clause, sorry

1 Like

Is this from the error message? If yes, thats not a guard clause, thats just printed out the failing function call with all values. Its the old way to display a FunctionClauseError, used until 1.4.x AFAIK.

1 Like

Ok, thanks for the explanation.

1 Like

changing from
{“body”: body}
to
{“body” => body}
seems to have fixed the error

Thanks!

1 Like

There is no such line in the code you have shown to us,

But I’m happy that you were able to solve the problem.

1 Like