Error: "no function clause matching in Keyword.get/3" when calling Ecto.changset

I’m running into the following errors, going through the Ecto getting started docs.

Calling

person = %Friends.Person{}
changeset = Friends.Person.changeset(person, %{})

Produces

** (FunctionClauseError) no function clause matching in Keyword.get/3     
    
    The following arguments were given to Keyword.get/3:
    
        # 1
        :last_name
    
        # 2
        :trim
    
        # 3
        true
    
    Attempted function clauses (showing 1 out of 1):
    
        def get(keywords, key, default) when is_list(keywords) and is_atom(key)
    
    (elixir 1.13.3) lib/keyword.ex:352: Keyword.get/3
    (ecto 3.8.4) lib/ecto/changeset.ex:1796: Ecto.Changeset.validate_required/3

person.ex


defmodule Friends.Person do
  use Ecto.Schema

  schema "people" do
    field(:first_name, :string)
    field(:last_name, :string)
    field(:age, :integer)
  end

  def changeset(person, params \\ %{}) do
    person
    |> Ecto.Changeset.cast(params, [:first_name, :last_name, :age])
    |> Ecto.Changeset.validate_required(:first_name, :last_name)
  end
end

migration

defmodule Friends.Repo.Migrations.CreatePeople do
  use Ecto.Migration

  def change do
    create table(:people) do
      add :first_name, :string
      add :last_name, :string
      add :age, :integer
    end

  end
end
1 Like

Hey @2FO welcome! The issue is that this line here should be:

|> Ecto.Changeset.validate_required([:first_name, :last_name])

Basically you’re passing in the atom :last_name into the argument that would be the options value. To pass in multiple fields that should be required you should use a list.

2 Likes

Hi,
I’m new to elixir and when I run my api it throws an error. Not sure what is wrong.

UserController

def index(conn, params, _current_user, _params) do
    page = Accounts.list_all_users(params)

    conn
    |> Scrivener.Headers.paginate(page)
    |> render("index.json", all_users: page.entries)
end

Error

[info] GET /api/manage/all_users
[debug] Processing with Pxf.Web.Admin.UserController.index/2
  Parameters: %{}
  Pipelines: [:api]
[info] Sent 500 in 278ms
[error] #PID<0.1130.0> running Pxf.Web.Endpoint (connection #PID<0.1129.0>, stream id 1) terminated
Server: localhost:8000 (http)
Request: GET /api/manage/all_users
** (exit) an exception was raised:
    ** (FunctionClauseError) no function clause matching in Keyword.get/3
        (elixir 1.14.2) lib/keyword.ex:388: Keyword.get(:default, :key, nil)
        (guardian 2.3.1) lib/guardian/plug.ex:373: Guardian.Plug.fetch_key/2
        (guardian 2.3.1) lib/guardian/plug.ex:141: Guardian.Plug.current_resource/2
        (pxf 0.1.0) lib/pxf/web/controllers/load_resource.ex:30: Pxf.Plug.LoadResource.call/2
        (pxf 0.1.0) Pxf.Router.api/2
        (pxf 0.1.0) lib/pxf/web/router.ex:1: Pxf.Router.__pipe_through1__/1
        (phoenix 1.6.15) lib/phoenix/router.ex:346: Phoenix.Router.__call__/2
        (pxf 0.1.0) lib/plug/error_handler.ex:80: Pxf.Router."call (overridable 3)"/2
        (pxf 0.1.0) lib/pxf/web/router.ex:1: Pxf.Router.call/2
        (pxf 0.1.0) lib/pxf/web/endpoint.ex:1: Pxf.Web.Endpoint.plug_builder_call/2
        (pxf 0.1.0) lib/pxf/web/endpoint.ex:1: Pxf.Web.Endpoint."call (overridable 3)"/2
        (pxf 0.1.0) lib/pxf/web/endpoint.ex:1: Pxf.Web.Endpoint.call/2
        (phoenix 1.6.15) lib/phoenix/endpoint/cowboy2_handler.ex:54: Phoenix.Endpoint.Cowboy2Handler.init/4
        (cowboy 2.9.0) /../dev/pxf-phoenix-v1.4/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
        (cowboy 2.9.0) /../dev/pxf-phoenix-v1.4/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
        (cowboy 2.9.0) /../dev/pxf-phoenix-v1.4/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
        (stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

Trying to figure it out but no luck so far.

This doesn’t appear to be related to the code in your controller at all; somewhere in your Guardian configuration you’ve got the atom :default where the package expects a keyword list.