Ghost's error handling leaves quite a lot to be desired at the moment:
- Our module which handles error logging, throwing & rendering tries to do a bit too much, without much clarity about what it is meant to do.
- There's some really dirty logic in the error handling module to cope with config & theme templates
- We have no support for proper log levels or debug messages, which makes it harder to debug ongoing issues than it should be.
- There's confusion between error code and status code, and dogfooding our own API via HTTP makes this worse.
- There's no centralised concept of codes or identifiers for a particular error also making debugging tricky.
- The API doesn't serve enough information about an error, particularly validations.
- We have a nice idea of an error message having 3 parts: error + context + help, but these were hardcoded throughout the codebase, and have now been moved out to the translations file, meaning they'll get auto-translated no matter where they are served/rendered.
- Themes are lacking in the ability to distinguish between 404 and 500 errors
There are already several issues open about improving these issues:
As well as a couple of client side issues, which mainly exist because the server side/API errors are so inconsistent & lacking in useful content:
So lets break this down a bit into a set of clearer questions / problems, and potential solutions:
1. Status codes vs error codes
All errors that are generated by Ghost itself, should have an error code which identifies them. This code can then be used for translations at the point of render/display, as well as being used for easier debugging.
Status codes are different, all errors can also have a status code that they should be served with, if sent back via HTTP, but this is a separate concept to an error code.
2. Messaging
We should try to pursue and improve upon our concept of errors having 3 parts to a message. The idea is:
- line 1 =
error = the actual error message. This may not have come from Ghost itself but we should endeavour to replace all errors generated elsewhere with clearer messaging.
- line 2 =
context = some information about where this error was thrown or why
- line 3 =
help = usually a URL, where to go to get more help about this error
To enable us to improve this messaging (as well as to enable us to have a concept of error code) all codes & messages should be stored in a centralised file, and the code that needs to send the error should pull the messaging out.
The messaging for an error should stay in English until such time as it's displayed in a place that has a concept of being translated. E.g. if it is getting sent in response to an API call that had a header, or it's being rendered as part of a theme which is translated (neither of these things exist yet).
3. Log levels & debugging
Two slightly different problems, potentially solvable by the same thing. This needs fixing, and should be pursued via the discussion in #2001.
4. Cleaning up the error module
There's a lot that can be done, I think, to separate out and refactor the code in server/errors/index.js into something a bit cleaner and clearer.
If we can come up with a plan on how to move forward with logging/debugging, then we can split out the part which is for logging errors nicely into something which uses whatever tools we decide on. The rendering part can then be separated and cleaned up in accordance #2030.
It's also worth noting, we might want to look at making our server-side error rendering with error templates more configurable, as Ghost swallowing all errors is a problem for people using ghost as a submodule / middleware of a larger app.
From an i18n perspective, the renderer is going to need to be aware of whether or not it should be translating these messages. E.g. if the admin panel is set to German, and we're rendering an admin error then the message should be translated, but if it's being rendered to the theme it needs to remain in English (until such time as we have a theme language/locale setting).
5. API errors
When being served from the API, errors need to not be stripped of all their useful info. As being discussed in #6050 we need to make sure we serve useful information for validation errors in particular.
Ideally, we should update our API to use the JSONAPI.org error format: http://jsonapi.org/format/#error-objects. This didn't exist when we first coded the API, but has now settled into something clear and usable.
6. Themes
As well as cleaning up the error page rendering logic, it would also be great to provide a bit more flexibility at the theme layer. Ideally, error pages rendered from the theme should provide a way to distinguish between a 404 error, and any other error.
The error template currently gets 3 pieces of data: message, code and stack. Code needs to be disambiguated between status code and error code, the message could be expanded to provide our 3 part error message.
We should consider providing error as a context (with a body class, like all other contexts), or whether that doesn't make sense (it sort of does for 404 errors, but not other errors).
Tasks:
Ghost's error handling leaves quite a lot to be desired at the moment:
There are already several issues open about improving these issues:
As well as a couple of client side issues, which mainly exist because the server side/API errors are so inconsistent & lacking in useful content:
So lets break this down a bit into a set of clearer questions / problems, and potential solutions:
1. Status codes vs error codes
All errors that are generated by Ghost itself, should have an error code which identifies them. This code can then be used for translations at the point of render/display, as well as being used for easier debugging.
Status codes are different, all errors can also have a status code that they should be served with, if sent back via HTTP, but this is a separate concept to an error code.
2. Messaging
We should try to pursue and improve upon our concept of errors having 3 parts to a message. The idea is:
error= the actual error message. This may not have come from Ghost itself but we should endeavour to replace all errors generated elsewhere with clearer messaging.context= some information about where this error was thrown or whyhelp= usually a URL, where to go to get more help about this errorTo enable us to improve this messaging (as well as to enable us to have a concept of error code) all codes & messages should be stored in a centralised file, and the code that needs to send the error should pull the messaging out.
The messaging for an error should stay in English until such time as it's displayed in a place that has a concept of being translated. E.g. if it is getting sent in response to an API call that had a header, or it's being rendered as part of a theme which is translated (neither of these things exist yet).
3. Log levels & debugging
Two slightly different problems, potentially solvable by the same thing. This needs fixing, and should be pursued via the discussion in #2001.
4. Cleaning up the error module
There's a lot that can be done, I think, to separate out and refactor the code in
server/errors/index.jsinto something a bit cleaner and clearer.If we can come up with a plan on how to move forward with logging/debugging, then we can split out the part which is for logging errors nicely into something which uses whatever tools we decide on. The rendering part can then be separated and cleaned up in accordance #2030.
It's also worth noting, we might want to look at making our server-side error rendering with error templates more configurable, as Ghost swallowing all errors is a problem for people using ghost as a submodule / middleware of a larger app.
From an i18n perspective, the renderer is going to need to be aware of whether or not it should be translating these messages. E.g. if the admin panel is set to German, and we're rendering an admin error then the message should be translated, but if it's being rendered to the theme it needs to remain in English (until such time as we have a theme language/locale setting).
5. API errors
When being served from the API, errors need to not be stripped of all their useful info. As being discussed in #6050 we need to make sure we serve useful information for validation errors in particular.
Ideally, we should update our API to use the JSONAPI.org error format: http://jsonapi.org/format/#error-objects. This didn't exist when we first coded the API, but has now settled into something clear and usable.
6. Themes
As well as cleaning up the error page rendering logic, it would also be great to provide a bit more flexibility at the theme layer. Ideally, error pages rendered from the theme should provide a way to distinguish between a 404 error, and any other error.
The error template currently gets 3 pieces of data:
message,codeandstack. Code needs to be disambiguated between status code and error code, the message could be expanded to provide our 3 part error message.We should consider providing
erroras a context (with a body class, like all other contexts), or whether that doesn't make sense (it sort of does for 404 errors, but not other errors).Tasks:
updateActiveThememethod