Resolved
Are mutations considered loads? I have added global-error-action to application and it never gets called when remote returns 500 response to a mutation. I’ve added a breakpoint in data-fetch namespace load-failed! function and it never gets called.
You’ve got a bug here
(= 403 status-code) (let [{:keys [security-id]} (ct/read (t/reader {}) body)]
(debounced-error
(str "Su petición está pidiendo acceso a recursos para los cuales no tiene acceso con REF " security-id ". Por favor contacta a soporte.")))so (t/reader {}) (I am assuming you’re using `
[cognitect.transit :as t]
will throw an error, the first argument should be a keyword like :jsonThanks
No, mutations are not considered loads. Other way around: loads are implemented as a mutation (which you can customize).
The default-result-action! in mutations does support the global error action…Triggering it is done byt this code:
(>defn trigger-global-error-action!
"When there is a `global-error-action` defined on the application, this function will checks for errors in the given
mutation `env`. If any are found then it will call the global error action function with `env`.
Typically used as part of the construction of a global default result handler for mutations.
Always returns `env`."
[env]
[::env => ::env]
(let [{:keys [app result]} env]
(enc/when-let [global-error-action (ah/app-algorithm app :global-error-action)
remote-error? (ah/app-algorithm app :remote-error?)
_ (remote-error? result)]
(global-error-action env))
env))
So you have to have a remote-error predicate defined (I think the default is not= status 200), and it has to return true for the result.
Yeah I did manage to get it to work, but I had some issues getting errors back, seems like keys that weren’t in the query get removed
keys in the query?
yes, if you return from the server map like {:error ""} then in the global error action you get {} , so I guess I need to add error keys to each query somehow for that to work
ended up just returning a vector on errors, which gets ignored by this mechanism
possible for the tx to be rewritten…For example :ui/* keys.
OH, that…your mutation has to declare what it expects as a return (mutation join) or your parser on the server might clip is
No the frontend clipped it
I saw the data in the http remote breakpoint
I can try to find again the place where it gets clipped
Error handling is kind of tough, since you’re responsible for your own server design. The error handling story in Fulcro is intentionally “left to the app”.
Hm…I would not expect Fulcro to be clipping it before that point. It’s getting the raw result from the remote and putting that in env and running it through the default-result-handler!…pretty sure, but not certain.
com.fulcrologic.fulcro.algorithms.tx-processing/combine-sends line 124
so yea, not possible to return “generic” errors (e.g. 401 session expired) as a response to transaction, keys get clipped here
since you probably don’t have it as a mutation join
Ah
ended up returning a vector for all my generic error needs
from remote I mean
then I get the data unmodified into the global error handler
Trying to remember why I did that…
I think it was to prevent spurious “extras” in the result from causing problems. It’s been a few years…
But think about it this way:
• If a mutation has a problem, then catching the exception on the server in the mutation and returning a proper value would cause the body to contain {mutation-sym error-data-from-mutation}. This allows each mutation to handle it’s own errors individually, and is what you want.
• If the server lets exceptions propagate all the way to the top, and you turn that into a status error, then you got NO proper errors from specific mutations. So that handling should be at a more global level. The “generic” status code is all that the mutation should be acting on. in this case.
So, that’s why the result if filtered. If you have a server bug that’s putting garbage into the result that doesn’t correspond to the top level “things” (query keys or mutations) then they are considered garbage, and there’s some change them being there can screw up the post processing of the result. There’s no way for Fulcro to “target” the correct mutation(s) with results.
That said, probably would be nice to just see the raw body/result somewhere in env if you wanted it.
I mean there’s a whole class of errors that stop the app effectively (such as users losing session, 500 errors due to bugs, 403 errors for whatever reason) that I don’t really need to handle in a meaningful fashion but I do need to be able to send some text from server to the client to show the user the general nature of the error (also makes it easier to debug problems than making a generic error popup and then having to look at logs for every user with a problem), but I understand what you’re saying
What I do for those is handle them in the http remote middleware. I add a toast container or something, and trigger mutations or toats or whatever from the network layer.
e.g.
(defn- wrap-bad-status [handler]
(fn [{:keys [status-code error body] :as resp}]
(cond
(= :network-error error) (debounced-error "Su solicitud falló porque se interrumpió la conexión de red o la solicitud estaba tardando demasiado.")
(= 599 status-code) (prim/transact! @app-atom '[(dataico.ui.user.auth/system-outage)])
(= 503 status-code) (debounced-error "Su solicitud falló porque el servidor no estaba disponible temporalmente.")
(= 403 status-code) (let [{:keys [security-id]} (ct/read (t/reader {}) body)]
(debounced-error
(str "Su petición está pidiendo acceso a recursos para los cuales no tiene acceso con REF " security-id ". Por favor contacta a soporte.")))
(= 490 status-code) (do
(debounced-message "Tu sesión ha caducado. Por favor autentícate de nuevo para continuar.")
(js/setTimeout #(scf/send! @app-atom :dataico.startup.model/startup :event/logout) 1000))
(= 401 status-code) (prim/transact! @app-atom '[(dataico.ui.user.auth/request-not-authorized)])
(not= 200 status-code) (debounced-error "Hubo un error inesperado. Inténtalo de nuevo."))
(handler resp)))
So I don’t even consider any of those classes of errors to be “mutation errors” and I don’t really want them triggering any kind of other default error handling, nor do I bother to make an error-action section in all of my mutations.
Most mutations that “fail” are failing for some reason you can’t really handle…and if you can handle it, you should set up the mutation join and processing to actually cope with it (in which case I don’t consider them hard errors, but “ok” responses that have a different handling path).
Yes, they are. Afk so sorry for lack of citation but it's in there somewhere.
Hm ok I will triple check but my load-failed function doesn't get called