Error Handling¶
Error handling is something that is done on multiple levels: Eg.: Form validation, network/fetch error handling, runtime errors. You could also argue that the fact that the codebase is making use of typescript and code generation from the various http services (graphql/REST) belongs to the same idiom of error handling in order to make the applications more robust.
Error Boundary¶
Error boundary was introduced in React 16 and makes it possible to implement a "catch all" feature catching "uncatched" errors and replacing the application with a component to the users that something went wrong. It is meant ato be a way of having a safety net and always be able to tell the end user that something went wrong. The apps are being wrapped in the error boundary handling which makes it possible to catch thrown errors at runtime.
Fetch and Error Boundary¶
Async operations and therby also fetch
are not being handled out of the box
by the React Error Boundary. But fortunately react-query
, which is being used
both by the REST services (Orval) and graphql (Graphql Code Generator), has a
way of addressing the problem. The QueryClient
can be configured to trigger
the Error Boundary system
if an error is thrown.
So that is what we are doing.
Fetch error classes¶
Two different types of error classes have been made in order to handle errors in the fetchers: http errors and fetcher errors.
Http errors are the ones originating from http errors and have a status code attached.
Fetcher errors are whatever else bad that could apart from http errors. Eg. JSON parsing gone wrong.
Both types of errors comes in two variants: "normal" and "critical". The idea is that only critical errors will trigger an Error Boundary.
For instance if you look at the
DBC Gateway fetcher
it throws a DbcGateWayHttpError
in case of a http error occurs.
DbcGateWayHttpError
extends the
FetcherCriticalHttpError
which makes sure to trigger the Error Boundary system.
Using Error.name¶
The reason why *.name is set in the errors is to make it clear which error was thrown. If we don't do that the name of the parent class is used in the error log. And then it is more difficult to trace where the error originated from.
Future considerations¶
The initial implementation is handling http errors on a coarse level:
If response.ok
is false then throw an error. If the error is critical
the error boundary is triggered.
In future version you could could take more things into consideration
regarding the error:
- Should all status codes trigger an error?
- Should we have different types of error level depending on request and/or http method?