Join-Table using uuids: value `"a770e948-dc85-4a6e-9b06-d31c735c8883"` for `course_id` in `insert` does not match type :id

Function to add a user to a course

  def user_add(course, user) do
    %CoursesUsers{}
    |>Ecto.Changeset.change()
    |>Ecto.Changeset.put_change(:user_id, user.id)
    |>Ecto.Changeset.put_change(:course_id, course.id)
    |>Repo.insert()
  end

Schema:

defmodule Courses.CoursesUsers do
  use Ecto.Schema

  @primary_key false
  schema "courses_users" do
    belongs_to :user, Accounts.User, primary_key: true
    belongs_to :course, Courses.Course, primary_key: true
  end
end

Migration:

    create table(:courses_users, primary_key: false) do
      add :course_id, references(:courses, type: :uuid), null: false
      add :user_id, references(:users, type: :uuid), null: false
     end
    create unique_index(:courses_users, [:course_id, :user_id])

Result:

** (exit) an exception was raised:
    ** (Ecto.ChangeError) value `"a770e948-dc85-4a6e-9b06-d31c735c8883"` for `App.Courses.CoursesUsers.course_id` in `insert` does not match type :id
        (ecto 3.5.6) lib/ecto/repo/schema.ex:889: Ecto.Repo.Schema.dump_field!/6
        (ecto 3.5.6) lib/ecto/repo/schema.ex:898: anonymous fn/6 in Ecto.Repo.Schema.dump_fields!/5
        (stdlib 3.14) maps.erl:233: :maps.fold_1/3
        (ecto 3.5.6) lib/ecto/repo/schema.ex:896: Ecto.Repo.Schema.dump_fields!/5
        (ecto 3.5.6) lib/ecto/repo/schema.ex:829: Ecto.Repo.Schema.dump_changes!/6
        (ecto 3.5.6) lib/ecto/repo/schema.ex:255: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4

Any help appreciated!

You need to tell Ecto what type the columns in the schema should be cast to/from; use either the type option to belongs_to or the @foreign_key_type setting.

1 Like

I actually have @forein_key_type on both the schemas I am using:

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  schema "courses" do
    ....
    many_to_many :user, App.Accounts.User, join_through: "courses_users"
    ....
  end

and

  @derive {Jason.Encoder, only: [:email]}
  @derive {Inspect, except: [:password]}
  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  schema "users" do
    ...
    many_to_many :courses, App.Courses.Course, join_through: "courses_users"
    .....
  end

I never needed the type option before because of this. But here it solved my problem, thanks.

@foreign_key_type only affects the schema it’s specified right above, and only affects belongs_to associations (since they are what calls field under the hood); your posted code for Courses.CoursesUsers doesn’t have it.