Absinthe graphql, how to print an ecto changeset as error?

Hey, I’m back with a weird problem while setting up absinthe with ecto changeset.

I found in this forum a way for formatting ecto changesets on absinthe error response.

But I have a weird behaviour:
When i do

changeset.errors |> Enum.map(fn {key, {key, context} -> [message: "...", details: context] end)

There is a problem it says:

 protocol Jason.Encoder not implemented for {:validation, :required} of type Tuple

but when I inspect the variable context:

[validation: :required]

So it is not a tuple, it’s an array? It should work right?
Let’s assume it’s actually a tuple, I can fix it using Tuple.to_list like this:

 changeset.errors
      |> Enum.map(fn {key, {value, context}} ->
        [message: "#{key} #{value}", details: Tuple.to_list(context)]
      end)

But it says:

(exit) an exception was raised:
    ** (ArgumentError) argument error
        :erlang.tuple_to_list([validation: :required])

Am I missing something? This is confusing me, if I inspect it, it says it’s an array. If I try to encode it using Jason it says it is a tuple


Actually It gives the same error if I just put this in my resolver:

{:error, [message: "adsfasdf", details: [validation: :required]]}

an exception was raised:
    ** (Protocol.UndefinedError) protocol Jason.Encoder not implemented for {:validation, :required} of type Tuple,

But it’s not a tuple?

The following

[validation: :required]

is syntactic sugar for a keyword list

[{:validation, :required}]

Since your details variable is a list of tuple you can convert it to a map (duplicated keys will be removed)

Map.new(details)

Or to a list of list

Enum.map(details, &Tuple.to_list/1)
3 Likes

Oh yeah, that makes sense. I was assuming lists could have keys ( so I was reading it has key => value). My bad! Thanks for your time :slight_smile:

1 Like