What does this absinthe.phoenix debugging output mean?

I’m trying to use Absinthe 1.4, currently on the latest published betas, and the Apollo Phoenix channel client. Currently building a basic authentication system, and I see this debug output when I hit one of my mutations:

[info] JOIN "__absinthe__:control" to Absinthe.Phoenix.Channel
  Transport:  Phoenix.Transports.WebSocket (2.0.0)
  Serializer:  Phoenix.Transports.V2.WebSocketSerializer
  Parameters: %{}
[info] Replied __absinthe__:control :ok
[debug] INCOMING "doc" on "__absinthe__:control" to Absinthe.Phoenix.Channel
  Transport:  Phoenix.Transports.WebSocket
  Parameters: %{"operationName" => nil, "query" => "mutation ($email: String!, $username: String!, $password: String!) {\n  signUp(email: $email, username: $username, password: $password) {\n    token\n    user {\n      id\n      username\n      __typename\n    }\n    __typename\n  }\n}\n", "variables" => %{"email" => "user@example.com", "password" => "[FILTERED]", "username" => "user"}}
[debug] ABSINTHE schema=AppWeb.API variables=%{"email" => "user@example.com", "password" => "[FILTERED]", "username" => "user"}
mutation ($email: String!, $username: String!, $password: String!) {
  signUp(email: $email, username: $username, password: $password) {
    user {

I have an IO.puts("here") in my resolver, so that should trigger. Additionally, I should see Ecto debugging output. None of that appears, though.

What does this debugging output mean? Seems the mutation is getting parsed correctly, but it isn’t hitting the resolver. Here’s the mutation definition:

    field :sign_up, non_null(:sign_in_payload) do
      arg :username, non_null(:string)
      arg :email, non_null(:string)
      arg :password, non_null(:string)

Here’s my socket definition, which I assume is where the channel maps to my GraphQL API:

defmodule AppWeb.UserSocket do
  use Phoenix.Socket
  use Absinthe.Phoenix.Socket

  ## Channels
  # channel "room:*", AppWeb.RoomChannel

  ## Transports
  transport :websocket, Phoenix.Transports.WebSocket
  # transport :longpoll, Phoenix.Transports.LongPoll

  # Socket params are passed from the client and can
  # be used to verify and authenticate a user. After
  # verification, you can put default assigns into
  # the socket that will be set for all channels, ie
  #     {:ok, assign(socket, :user_id, verified_user_id)}
  # To deny connection, return `:error`.
  # See `Phoenix.Token` documentation for examples in
  # performing token verification on connect.
  def connect(_params, socket) do
    {:ok, assign(socket, :absinthe, %{schema: AppWeb.API})}

  # Socket id's are topics that allow you to identify all sockets for a given user:
  #     def id(socket), do: "user_socket:#{socket.assigns.user_id}"
  # Would allow you to broadcast a "disconnect" event and terminate
  # all active sockets and channels for a given user:
  #     AppWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
  # Returning `nil` makes this socket anonymous.
  def id(_socket), do: nil


Hey! What response do you get from the server on the client side?

Network error: undefined.

Just wish I could figure out why it isn’t hitting my resolvers.

BTW, I’ve pushed my code here:

Unfortunately it uses a binary dependency, so requires that Erlang be built with --enable-dirty-schedulers. It also requires libsodium-devel to be installed since it uses Macaroons for authentication. But maybe there’s something obviously wrong in how I set up my socket or schema that’d be an easy fix?

If not, there’s an included Vagrantfile that spins up a ready-to-run environment, or I can create sample code without the Macaroons dependency.

I just removed the macaroons dependency:

The above code compiles with warnings, but should demonstrate the error. To replicate, clone, then run:

cd assets
npm install
cd ..
iex -S mix phx.server

Wait for the pages to build, then visit http://localhost:4000/signup. Create an account, click the button. In the console, among the Postgres connection errors, you should see the debugging output I alluded to.

Changing the name of the mutation from signUp to signUp1 in the client-side code changes nothing (I.e. it doesn’t throw an error when it hits the server, which doesn’t define a signUp1 mutation.) Likewise, changing the schema assign to a module that doesn’t exist in the socket definition changes nothing. I feel like I forgot to connect something to my socket/endpoint, but I’ve reread the README.md multiple times, and if I’m missing something then I can’t spot it.

Thanks for any help.

Ah, figured it out. I inserted some logging code in the channel. My code was bad, caused a crash, and in the crash I found my answer:

** (FunctionClauseError) no function clause matching in Absinthe.Logger.log_run/2
    (absinthe) lib/absinthe/logger.ex:54: Absinthe.Logger.log_run(:debug, {{:ok, %{errors: [%{locations: [%{column: 0, line: 5}], message: "Cannot query field \"id\" on type \"User\"."}]}}})
    (absinthe_phoenix) lib/absinthe/phoenix/channel.ex:50: Absinthe.Phoenix.Channel.handle_in/3
    (phoenix) lib/phoenix/channel/server.ex:244: anonymous fn/4 in Phoenix.Channel.Server.handle_info/2
    (app) lib/app_web/endpoint.ex:1: AppWeb.Endpoint.instrument/4
    (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:686: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

So it appears my schema is missing a field, which is fine, but I wish this had been reported to me somehow. I don’t even see it in the Apollo Phoenix client.

I filed this issue with a few more details.

1 Like