In my GraphQL API there is a schema.ex file with mutation which creates a new user:
@desc "Register a new user"
field :register_user, type: :user_type do
arg(:input, non_null(:user_input_type))
resolve(&Resolvers.UserResolver.register_user/3)
end
user_resolver.ex
def register_user(_, %{input: input}, _) do
Accounts.create_user(input)
end
user.ex
def changeset(user, attrs) do
user
|> cast(attrs, [:first_name, :last_name, :login, :email, :password, :password_confirmation, :role])
|> validate_required([:first_name, :last_name, :login, :email, :password, :password_confirmation, :role])
|> validate_format(:email, ~r/@/)
|> update_change(:email, &String.downcase(&1))
|> validate_length(:password, min: 6, max: 50)
|> validate_confirmation(:password)
|> unique_constraint(:email)
|> hash_password
end
If I create a new user and all the conditions from the changeset will be fulfilled everything is ok. But if I for instance put an e-mail which is already in the DB (it should be unique) I get an error:
mutation {
registerUser(input: {firstName: "Jan", lastName: "Nowak", login: "jnowak", email: "bob1@bob.com", password: "test123
", passwordConfirmation: "test123"}) {
firstName
}
}
---
[debug] QUERY ERROR db=9.0ms
INSERT INTO "users" ("email","first_name","last_name","login","password_hash","role","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING "id" ["bob1@bob.com", "Jan", "Nowak", "jnowak", "$argon2i$v=19$m=65536,t=6,p=1$uAEr21JgCiN2Vq8g3c7abA$u/cyXghpQvq4hg8VoszWkIREErb7qDSlNm+1J6PiSGg", "user", {{2018, 11, 15}, {18, 32, 54, 147581}}, {{2018, 11, 15}, {18, 32, 54, 150554}}]
[info] Sent 500 in 1200ms
[error] #PID<0.411.0> running MdbmsBackendWeb.Endpoint (cowboy_protocol) terminated
Server: localhost:4000 (http)
Request: POST /api/graphiql
** (exit) an exception was raised:
** (Protocol.UndefinedError) protocol Enumerable not implemented for #Ecto.Changeset<action: :insert, changes: %{email: "bob1@bob.com", first_name: "Jan", last_name: "Nowak", login: "jnowak", password_confirmation: "test123", password_hash: "$argon2i$v=19$m=65536,t=6,p=1$uAEr21JgCiN2Vq8g3c7abA$u/cyXghpQvq4hg8VoszWkIREErb7qDSlNm+1J6PiSGg", role: "user"}, errors: [email: {"has already been taken", []}], data: #MdbmsBackend.Accounts.User<>, valid?: false>. This protocol is implemented for: DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Postgrex.Stream, Range, Stream
(elixir) /private/tmp/elixir-20180620-66895-1xvgf6i/elixir-1.6.6/lib/elixir/lib/enum.ex:1: Enumerable.impl_for!/1
(elixir) /private/tmp/elixir-20180620-66895-1xvgf6i/elixir-1.6.6/lib/elixir/lib/enum.ex:141: Enumerable.reduce/3
(elixir) lib/enum.ex:1911: Enum.reverse/1
(elixir) lib/enum.ex:2588: Enum.to_list/1
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:351: Absinthe.Phase.Document.Execution.Resolution.split_error_value/1
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:341: Absinthe.Phase.Document.Execution.Resolution.put_result_error_value/5
(elixir) lib/enum.ex:1899: Enum."-reduce/3-lists^foldl/2-0-"/3
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:256: Absinthe.Phase.Document.Execution.Resolution.build_result/4
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:153: Absinthe.Phase.Document.Execution.Resolution.do_resolve_fields/6
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:72: Absinthe.Phase.Document.Execution.Resolution.walk_result/5
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:53: Absinthe.Phase.Document.Execution.Resolution.perform_resolution/3
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:24: Absinthe.Phase.Document.Execution.Resolution.resolve_current/3
(absinthe) lib/absinthe/pipeline.ex:274: Absinthe.Pipeline.run_phase/3
(absinthe_plug) lib/absinthe/plug.ex:421: Absinthe.Plug.run_query/4
(absinthe_plug) lib/absinthe/plug.ex:247: Absinthe.Plug.call/2
(phoenix) lib/phoenix/router/route.ex:147: Phoenix.Router.Route.forward/4
(phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
(mdbms_backend) lib/mdbms_backend_web/endpoint.ex:1: MdbmsBackendWeb.Endpoint.plug_builder_call/2
(mdbms_backend) lib/plug/debugger.ex:122: MdbmsBackendWeb.Endpoint."call (overridable 3)"/2
(mdbms_backend) lib/mdbms_backend_web/endpoint.ex:1: MdbmsBackendWeb.Endpoint.call/2
I wonder what is the reason of this UnderfinedError. It causes also a problem when I use this API in my frontend. Console.log returns “POST 500 (Internal Server Error)”, but only when I do not fullfil conditions from the changeset.
I hope this information will help you understand my issue.