I’ve pulled your repo down as is and it fails, but once I add the channel module definition, it works as intended. In your reproduction repo, your channel module does not exist and any attempt to join a channel should fail. In fact, if you read your error message carefully, you can actually guess what it’s trying to do. Now, it does require some experience, but I can walk you through my thought process.
[error] Ranch listener MusicJamServerWeb.Endpoint.HTTP had connection process started with :cowboy_clear:start_link/4 at #PID<0.5779.0> exit with reason: {:undef, [{MusicJamServerWeb.RoomChannel, :child_spec, [{MusicJamServerWeb.Endpoint, {#PID<0.5779.0>, #Reference<0.3249608392.111935491.56526>}}], []}, {Phoenix.Channel.Server, :join, 4, [file: 'lib/phoenix/channel/server.ex', line: 24]}, {Phoenix.Socket, :handle_in, 4, [file: 'lib/phoenix/socket.ex', line: 598]}, {Phoenix.Endpoint.Cowboy2Handler, :websocket_handle, 2, [file: 'lib/phoenix/endpoint/cowboy2_handler.ex', line: 145]}, {:cowboy_websocket, :handler_call, 6, [file: '/home/patrick/Code/music_jam_server/deps/cowboy/src/cowboy_websocket.erl', line: 528]}, {:cowboy_http, :loop, 1, [file: '/home/patrick/Code/music_jam_server/deps/cowboy/src/cowboy_http.erl', line: 257]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}]
There are two halves of these error that are important to us:
:undef, [{MusicJamServerWeb.RoomChannel, :child_spec, [{MusicJamServerWeb.Endpoint, {#PID<0.5779.0>, #Reference<0.3249608392.111935491.56526>}}], []},
and then every under it. What this looks like is a trace, specifically a function trace. You can tell since the output reads like a MFA (module-function-arguments). MFA are typically used with apply/3
, so things like apply(String, :at, ["example", 2])
are used for somewhat dynamic calls. Now, take a look at first line:
{MusicJamServerWeb.RoomChannel, :child_spec, [{MusicJamServerWeb.Endpoint, {#PID<0.5779.0>, #Reference<0.3249608392.111935491.56526>}}]
This is definitely a MFA like structure, a module, a function atom and the leading arguments. So for one, if we assume that this is the case, the module MusicJamServerWeb.RoomChannel
must exist, but it does not in your repository. Furthermore, the :child_spec
function is critically important in Erlang; it defines the specification to start child processes. With that being said, we can check the Phoenix socket code for this behaviour: phoenix/server.ex at v1.6 · phoenixframework/phoenix · GitHub
Here the channel is expected to have a function child_spec/1
, but since the module is undefiined, you’ll run into the exact problem you have. This can easily be replicated here:
iex(2)> apply(DoesNotExist, :hello, [])
** (UndefinedFunctionError) function DoesNotExist.hello/0 is undefined (module DoesNotExist is not available)
DoesNotExist.hello()
If you go back to the Phoenix code, it attempts to start the child process based off that child specification call, but since you’re trying to call a function that doesn’t exist, it outright fails.