Changeset Error "is invalid"

Hello geeks, I’m still a newbie so my code could be not that good and my question could seem trivial, so I really appreciate your help.

I have a question. I have and embedded schema for playerErrors inside the main schema log
using embeds_many :playerErrors, PlayerError in log.ex and in the migration file I wrote this add :playerErrors, {:array, :jsonb}, default: [].

And in the log changeset I wrote this

    |> cast_embed(:playerErrors)
    |> put_embed(:playerErrors, attrs[:playerErros])

This how the playerErrors looks like:

[
  %{_id: "5dfed5631d12bf790c61465f", errorCount: 0, errorType: "DET_NOUN"},
  %{_id: "5dfed5631d12bf790c61465e", errorCount: 0, errorType: "FIRST"},
  %{_id: "5dfed5631d12bf790c61465d", errorCount: 0, errorType: "ADP_NOUN"},
  %{_id: "5dfed5631d12bf790c61465c", errorCount: 0, errorType: "ADJ_NOUN"},
  %{_id: "5dfed5631d12bf790c61465b", errorCount: 0, errorType: "ADV_VERB_NOUN"}
]

But whenever I attempt to create a log I get this changeset error:

{:error,
 #Ecto.Changeset<
   action: :insert,
   changes: %{
  
     playerErrors: [
       #Ecto.Changeset<
         action: :insert,
         changes: %{errorCount: 0, errorType: "DET_NOUN"},
         errors: [],
         data: #Lean.GameLogs.PlayerError<>,
         valid?: true
       >,
       #Ecto.Changeset<
         action: :insert,
         changes: %{errorCount: 0, errorType: "FIRST"},
         errors: [],
         data: #Lean.GameLogs.PlayerError<>,
         valid?: true
       >,
       #Ecto.Changeset<
         action: :insert,
         changes: %{errorCount: 0, errorType: "ADP_NOUN"},
         changes: %{errorCount: 0, errorType: "ADJ_NOUN"},
         errors: [],
         data: #Lean.GameLogs.PlayerError<>,

         valid?: true
       >,
       #Ecto.Changeset<
         action: :insert,
         changes: %{errorCount: 0, errorType: "ADV_VERB_NOUN"},
         errors: [],
         data: #Lean.GameLogs.PlayerError<>,
         valid?: true
       >
     ],
   },
   errors: [
     playerErrors: {"is invalid", [type: {:array, :map}]}
   ],
   data: #Lean.GameLogs.Log<>,
   valid?: false
 >}

Can someone please help me?
Thanks in advance.

Try removing the put_embed call as a start. It should only be used when programmatically changing the field and not when accepting external parameters to construct it.

1 Like

thank you so much, but I tried it and I got a new type of error

[debug] QUERY OK db=15.0ms idle=219.0ms
begin []
[debug] QUERY OK db=0.0ms
rollback []
** (CaseClauseError) no case clause matching: {:id, :id, :id}
    (ecto) lib/ecto/embedded.ex:141: Ecto.Embedded.autogenerate_id/5

    (ecto) lib/ecto/embedded.ex:112: Ecto.Embedded.to_struct/4
    (ecto) lib/ecto/embedded.ex:81: anonymous fn/6 in Ecto.Embedded.prepare_each/5
    (elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ecto) lib/ecto/embedded.ex:78: Ecto.Embedded.prepare_each/5
    (ecto) lib/ecto/embedded.ex:63: anonymous fn/6 in Ecto.Embedded.prepare/5
    (stdlib) maps.erl:257: :maps.fold_1/3
    (ecto) lib/ecto/repo/schema.ex:245: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
    (ecto) lib/ecto/repo/schema.ex:919: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/6
    (ecto_sql) lib/ecto/adapters/sql.ex:903: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
    (db_connection) lib/db_connection.ex:1427: DBConnection.run_transaction/4

what does it mean?

Seems to be a problem with auto-generating IDs for the embeds. Can you show your Log and PlayerError schema files?

1 Like

Sure, here you go
log.ex

defmodule Lean.GameLogs.Log do
  use Ecto.Schema
  import Ecto.Changeset

  alias Lean.GameLogs.SentenceLog
  alias Lean.GameLogs.PlayerError
  alias LeanWeb.DataParser

  schema "logs" do
    field :dayTime, :string
    field :gameName, :string
    field :levelIndex, :integer
    field :playerID, :string
    field :playerName, :string
    field :restarted, :boolean, default: false
    field :score, :integer
    field :sessionID, :integer
    field :timeTaken, :float
    embeds_many :sentenceLogs, SentenceLog
    embeds_many :playerErrors, PlayerError


    timestamps()
  end

  @doc false
  def changeset(log, attrs) do
    log
    |> cast(attrs, [:gameName, :score, :levelIndex, :sessionID, :playerID, :playerName, :timeTaken, :dayTime, :restarted])
    |> validate_required([:gameName, :score, :levelIndex, :sessionID, :playerID, :playerName, :timeTaken, :dayTime, :restarted, :sentenceLogs, :playerErrors])
    |> cast_embed(:sentenceLogs)
    |> cast_embed(:playerErrors)
  end
end

playerError.ex

defmodule Lean.GameLogs.PlayerError do
  use Ecto.Schema
  import Ecto.Changeset

  schema "playererrors" do
    field :_id, :string
    field :errorCount, :integer
    field :errorType, :string

    timestamps()
  end

  @doc false
  def changeset(player_error, attrs) do
    player_error
    |> cast(attrs, [:errorType, :errorCount])
    |> validate_required([:errorType, :errorCount])
  end
end

Change this to: embedded_schema "playererrors" do.

2 Likes