Hey all! I'm just now checking out the latest version of pathom3. With the earlier version I was using, if I called (throw (ex-info "My custom error" {:error/code :my-error-code})) from a resolver, I could access the error data from the response by accessing ::p.error/error-data The latest version simplifies the error object and I'm only seeing :tx and :entity surfacing. When looking at com.wsscode.pathom3.error/datafy-processor-error the error I throw is available in ex-cause, but that's not returned from the function. I was wondering if there's something I'm missing to surface the thrown error data. Cheers!
This is probably more like feedback for pathom than something I would recommend anyone else do, but I have the following in a side project 🙈
(alter-var-root #'com.wsscode.pathom3.connect.runner/processor-exception (constantly (fn [_ ex] ex)))
(alter-var-root #'com.wsscode.pathom3.connect.runner/report-resolver-error (constantly (fn [_ _ ex] (throw ex))))Thanks for sharing! Never used alter-var-root, but that's very powerful.
hi @dehli, that was indeed an intended change to simplify the error, after the change you can get your ex-data as before in the following way:
(try
(p.eql/process env {:users [{:user/id 1}]}
[{:users [:user/full-name]}])
(catch Throwable e
(ex-data (ex-cause e))))Pathom will wrap the error, but still use your original as the error cause, so you can grab it back with ex-cause
Thanks! I was using p.a.eql/boundary-interface so the errors would be automatically converted into maps. Would you recommend switching to regular process and constructing the map from ex-cause like you proposed?
that's a good question, the boundary api is designed to make something that can return data over the network, thus it does that kind of serialization. not using the boundary api is surely an option. another one is to make a plugin for ::pcr/wrap-resolver-error, where you can manipulate the error before it flows up
can you tell me more about your specific case? I think that is a part that is still up to change, if we find a better way to handle it
ps: please note that you might get an error there that is not about resolver exceptions, it could also be: • resolver missed returning some required attribute • resolver returned an invalid response (something that isn't a map or nil)
Of course! I'm using boundary-interface right at the edge before sending the response to the consumer (so needs to be serializable). I currently throw custom exceptions from mutations when certain business rules aren't met. The consumer then reads those custom exceptions and reacts appropriately (I typically store all relevant data in the exception's data so client would read it from error-data with old pathom code). Hope that makes sense!
humm, gotcha, but that means the error you are bringing about is from a mutation? or its from some follow-up read from a mutation? Im trying to pin if the exception is coming from the mutation or a resolver
Ahh, sorry for not being clear. I use that pattern in both resolvers and mutations. In my codebase, mutations have more types of exceptions that can be thrown (spec errors, business logic, etc.) whereas resolvers will generally just throw (ex-info "Unauthorized" {:error/code :unauthorized}) if you try to access data that you don't have permissions for. In both cases I throw an ex-info with a unique :error/code.