2

I am trying to resolve the following (this is the return value of my resolver function, and I am passing it to the resolve macro):

 {:ok,
 %{
   collection: nil,
   errors: %{
     recoverable: [
       %{
         __exception__: true,
         __recoverable__: true,
         message: %{
           color: %{
             exterior: ["is invalid"], 
             interior: ["is invalid"]
           }
         },
         type: :vehicle_invalid
       }
     ],
     unrecoverable: []
   }
 }}

This returns this classic error:

** (Protocol.UndefinedError) protocol String.Chars not implemented for %{color: %{exterior: ["is invalid"], interior: ["is invalid"]}} of type Map. This protocol is implemented for the following type(s): Money, Postgrex.Copy, Postgrex.Query, Floki.Selector.AttributeSelector, Floki.Selector, Floki.Selector.Functional, Floki.Selector.Combinator, Floki.Selector.PseudoClass, Decimal, Float, DateTime, Time, List, Version.Requirement, Atom, Integer, Version, Date, BitString, NaiveDateTime, URI

which I get, it doesn't know how to convert the map to a string, but that leads to my actual question:

I am wondering why the top level errors map can get parsed fine, but not the nested messages map, would love some guidance, thanks!

Note: Our pattern is to have Ecto style validation errors come back under our own data, rather than the top level Graph query errors, hence the :ok tuple rather than resolving an :error tuple

Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
mackshkatz
  • 861
  • 8
  • 19
  • Are you applying some middleware to your errors? Is there any function in `schema.ex` that looks like this: `defp apply(middleware, :errors, _field, _) do` ? – Peaceful James Aug 11 '20 at 18:25
  • @PeacefulJames thanks for the reply, I posted an answer below once I realized what was happening :| – mackshkatz Aug 11 '20 at 21:11

1 Answers1

2

Well, it actually was something super obvious, in my graph schema I specify the :message field as a :string type, and... it is obviously a map. I figure I will leave this post up just in case someone else is doing something similarly obvious and this helps them out hah.

A couple options I could go with for those out there following along:

  • Have my :message field be a struct of some kind that implements the String.Chars protocol, allowing me to just pass it all the way up to the graph schema, leaving that field as a :string type, then when graph calls to_string on that, it handles it itself implicitly.
  • I could define a custom scalar that specifies a serialize https://hexdocs.pm/absinthe/Absinthe.Schema.Notation.html#serialize/1 function to parse the :message value on the way out, but that would likely entail coupling the graph schema too tightly to the underlying structure
  • Simply have the :message value of my map be a string...
mackshkatz
  • 861
  • 8
  • 19