Protocol Enumerable not implemented for error with guardian login

I’ve got the same error (so frustrating!):

Protocol.UndefinedError at POST /login

protocol Enumerable not implemented for %Dog.UserManager.User{meta: #Ecto.Schema.Metadata<:loaded, “users”>, id: 3, inserted_at: ~N[2019-07-15 05:56:22], password: “$argon2id$v=19$m=131072,t=8,p=4$jinhp9gEDVENO2PIdm5zkg$ovideTURD59gCoqtE6UUuYZ/32YMnpgppuRf0NFAJ/k”, updated_at: ~N[2019-07-15 05:56:22], username: “me”}. This protocol is implemented for: Ecto.Adapters.SQL.Stream, Postgrex.Stream, DBConnection.Stream, DBConnection.PrepareStream, HashSet, Range, Map, Function, List, Stream, Date.Range, HashDict, GenEvent.Stream, MapSet, File.Stream, IO.Stream

The stack trace seems to point to my SessionController:

* elixir /home/build/elixir/lib/elixir/lib/enum.ex:1Enumerable.impl_for!/1
* elixir /home/build/elixir/lib/elixir/lib/enum.ex:141Enumerable.reduce/3
* elixir lib/enum.ex:3015Enum.reverse/1
* elixir lib/enum.ex:2647Enum.to_list/1
* elixir lib/map.ex:181Map.new_from_enum/1
* guardian lib/guardian.ex:573Guardian.encode_and_sign/4
* guardian lib/guardian/plug.ex:208Guardian.Plug.sign_in/5
* lib/dog_web/controllers/session_controller.ex:29DogWeb.SessionController.login_reply/2
* lib/dog_web/controllers/session_controller.ex:1DogWeb.SessionController.action/2
* lib/dog_web/controllers/session_controller.ex:1DogWeb.SessionController.phoenix_controller_pipeline/2
* phoenix lib/phoenix/router.ex:288Phoenix.Router.__call__/2
* lib/dog_web/endpoint.ex:1DogWeb.Endpoint.plug_builder_call/2
* lib/plug/debugger.ex:122DogWeb.Endpoint."call (overridable 3)"/2
* lib/dog_web/endpoint.ex:1DogWeb.Endpoint.call/2
* phoenix lib/phoenix/endpoint/cowboy2_handler.ex:40Phoenix.Endpoint.Cowboy2Handler.init/2
* cowboy /Users/7stud/phoenix_apps/dog/deps/cowboy/src/cowboy_handler.erl:41:cowboy_handler.execute/2
* cowboy /Users/7stud/phoenix_apps/dog/deps/cowboy/src/cowboy_stream_h.erl:296:cowboy_stream_h.execute/3
* cowboy /Users/7stud/phoenix_apps/dog/deps/cowboy/src/cowboy_stream_h.erl:274:cowboy_stream_h.request_process/3

Here’s my SessionController:

defmodule DogWeb.SessionController do
  use DogWeb, :controller
  alias Dog.{UserManager, UserManager.User, UserManager.Guardian}

  def new(conn, _) do
    changeset = UserManager.change_user(%User{})
    maybe_user = Guardian.Plug.current_resource(conn)
    if maybe_user do
      redirect(conn, to: "/secret")
    else
      render(conn, "new.html",
             changeset: changeset,
             action: Routes.session_path(conn, :login)
      ) 
    end
  end

  def login(conn, 
            %{"user" => %{"username" => username,
                          "password" => password}})
  do
    UserManager.authenticate_user(username, password)
    |> login_reply(conn)
  end

  def login_reply({:ok, user}, conn) do
    conn
    |> put_flash(:info, "Welcome back!")
    |> Guardian.Plug.sign_in(Guardian, user)
    |> redirect(to: "/secret")
  end
  def login_reply({:error, reason}, conn) do
    conn
    |> put_flash(:error, to_string(reason))
    |> new(%{})
  end

  def logout(conn, _) do
    conn
    |> Guardian.Plug.sign_out(Guardian)
    |> redirect(to: "/login")
  end

end

I checked the Guardian.Plug docs for the sign_in() function:

sign_in(conn, impl, resource, claims \\ %{}, opts \\ []) 

sign_in(
  Plug.Conn.t(),
  module(),
  any(),
  Guardian.Token.claims(),
  Guardian.options()
) :: Plug.Conn.t()

And, I"m calling sign_in() with the correct types for the arguments. I’m stuck.

Here’s my config.exs:

use Mix.Config

config :dog,
  ecto_repos: [Dog.Repo]

config :dog, Dog.Repo,
  datbase: "dog",
  username: "7stud",
  password: "",
  hostname: "localhost",
  port: "5432"

config :dog, Dog.UserManager.Guardian,
  issuer: "dog",
  secret_key: "e8UPW0Doh0iBonm8ZK0RJVzaAA8r+Jgw4t3lVEoB1SiByke/V9cxcz//1iPkpVrq"

# Configures the endpoint
config :dog, DogWeb.Endpoint,
  url: [host: "localhost"],
  secret_key_base: "xpVFSaAFJZ8xUEhWLrzT/sTvL/Z6y+mSvfobiKiKanWexNwL2Wj2EbRXr7V9fQSj",
  render_errors: [view: DogWeb.ErrorView, accepts: ~w(html json)],
  pubsub: [name: Dog.PubSub, adapter: Phoenix.PubSub.PG2]

# Configures Elixir's Logger
config :logger, :console,
  format: "$time $metadata[$level] $message\n",
  metadata: [:request_id]

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"

I’m using a UserManager context for the public interface:

defmodule Dog.UserManager do
  @repo Dog.Repo
  alias Dog.UserManager.User
  alias Argon2

  import Ecto.Query, only: [from: 2]

  def list_users() do
    @repo.all(User)
  end

  def get_user(id) do
    @repo.get!(User, id)
  end

  def change_user(%User{}=user) do
    User.changeset(user, %{})
  end

  def insert_user(attrs) do
    %User{}
    |> User.changeset(attrs)
    |> @repo.insert()
  end

  def delete_user(%User{}=user) do
    @repo.delete(user)
  end

  def authenticate_user(username, plain_text_password) do
    query = from u in User, where: u.username == ^username
    case @repo.one(query) do
      nil ->
        Argon2.no_user_verify()
        {:error, :invalid_credentials}
      user ->
        if Argon2.verify_pass(plain_text_password, user.password) do
          {:ok, user}
        else
          {:error, :invalid_credentials}
        end
    end
  end


end

Here’s my directory structure:

~/phoenix_apps/dog$ tree lib
lib
├── dog
│   ├── application.ex
│   ├── repo.ex
│   └── user_manager
│       ├── error_handler.ex
│       ├── guardian.ex
│       ├── pipeline.ex
│       ├── user.ex
│       └── user_manager.ex
├── dog.ex
├── dog_web
│   ├── channels
│   │   └── user_socket.ex
│   ├── controllers
│   │   ├── page_controller.ex
│   │   └── session_controller.ex
│   ├── endpoint.ex
│   ├── gettext.ex
│   ├── router.ex
│   ├── templates
│   │   ├── layout
│   │   │   └── app.html.eex
│   │   ├── page
│   │   │   ├── index.html.eex
│   │   │   └── protected.html
│   │   └── session
│   │       └── new.html.eex
│   └── views
│       ├── error_helpers.ex
│       ├── error_view.ex
│       ├── layout_view.ex
│       ├── page_view.ex
│       └── session_view.ex
└── dog_web.ex