Fork me on GitHub

I am trying out the error handling in Pathom 3 and I couldn’t get attribute-error function to return a non-nil result. I have a query by ident like [{[:user/id 1] [:user/name]}] and I’ve got the name resolver always throw an Excecption, and lenient mode on. I get what you’d expect:

{[:user/id 1] #:com.wsscode.pathom3.connect.runner{:attribute-errors #:user{:name #:com.wsscode.pathom3.error{:cause :com.wsscode.pathom3.error/node-errors,
                                                                                                                                      :node-error-details ......
But when I call (attribute-error response [:user/id 1]) I get back nil. I’ve looked at implementation of that function and subfunctions and it basicall uses com.wsscode.pathom3.connect.planner/index-attrs and com.wsscode.pathom3.connect.planner/index-ast and com.wsscode.pathom3.connect.runner/node-run-stats . And then I looked at my meta or response and saw that index-attrs was missing, and node-run-stats is empty map…. so of course this didn’t work. What am I doing wrong?


the error is always per entity, and attribute error is about an attribute ,an ident query like [:user/id 1] will never have an error on itself because its just a data forward thing, the error will always be inside of it (meaning you need to look for the attribute error at that level), makes sense?


ok, so I need to request (attribute-error response :user/name)?


more like: (attribute-error (get response [:user/id 1]) :user/name)]


the thing is that node-run-stats is empty and looking at the code it attribute-error it needs to have something in there


note each map has its own meta with status details


not just the root


So I’ll have to walk the result to log errors I think


if you want to log errors, its better to use a plugin to wrap error events, its gonna be easier than traversing


Yeah I see that


that said, traversing is possible, and that's what Pathom Viz does to compute the trace tree:


but for observability, an error plugin is easier and more efficient


Let’s say you’ve got a button, and it’s got ::button/shape resolver, which describes a “type” (e.g. either circle or a square), and the circle shape has radius, but the square has width, height as attributes, how would you write that resolver output?

(pco/defresolver button-shape [{::button/keys [id]}]
  {::pco/output [{::button/shape [::shape/type ::shape/radius ::shape/width ::shape/height]}]}
   (let [b (get-button id)]
     (if (= "circle" (:shape b))
       {::shape/type :circle ::shape/radius (:radius b)}
       {::shape/type :square ::shape/width (:width b) ::shape/height (:height b)}))})


You could have a separate resolver for each shape. So a resolver for circle/id and another for square/id. This way Pathom has a resolver (and a <table-name>/id) for each grouping of attributes. Of course I realise that's not answering the question so please take it as a comment.


How would that work? Union query?


I was suggesting that the schema be changed to accommodate Pathom, so no more types. That's just how I might go about it, given you only have 2 types, and there aren't even any attributes in common. I would have a circle resolver and a square resolver.


I think your approach is fine, you could go with Unions to make it more specific but I dont think its nescessary (the add complexity of dealing with unions is not worth given the difference in attributes is so short)


But without unions I have problem where th resolver is in error because it is not returning all the requested properties


Well for those attributes you could return nil or your own key, say :not-needed. That would stop the error. But maybe there's a better way...


you can also use optionality to handle the missing data cases, like:

(p.eql/process env [{::button/shape [::shape/type (pco/? ::shape/radius) (pco/? ::shape/width) (pco/? ::shape/height)]}


or returning nils, as @U0D5RN0S1 mentioned


Is it possible to get whether a :node-id is optional from within the runner? (or does that question not make sense 🙂). I'm looking through the source code and trying to address My thoughts are inside of pcr/run-or-node! after we've gone through all the nodes, if the key is optional, rather than failing fast we could continue w/ execution. Also hi! 👋


just sent a possible fix, let me know if works in your scenario 🙂


about the question o optional node, a optional node doesn't make sense, because the node might have both required and optional things to fulfill, the optionality is something we check at the index-ast via the attribute key (looking for the optional param there)


Thanks! That looks like it would work for my scenario. I'll pull latest for my project. Thanks for answering the node question! That makes sense to me.


currently every OR node can have only one attribute expected, but since this is a thing that's not used extensively (this may change in the future with better optimizations), I believe we still gonna find some rough edges, and fix as we find them 🙂


Just confirmed that the fix worked for my more complicated example 🎉 Thanks for your help and explanation! And I'll happily continue to help surface any rough edges as I find them 🙂

🎉 1