Error Handling
Understand how you can handle the errors of the REST API application.
Introduction
When you start a new Athenna project, error and exception handling is already configured for you. But you can configure your own extending the Athenna error handler. We'll dive deeper into how to do that throughout this documentation.
This documentation will cover about error handling in the REST API application, which means that only errors that happens inside routes and bellow that will be handled:
import { Route } from '@athenna/http'
// If AppController.show throws, HttpExceptionHandler will handle it 👈
Route.get('/', 'AppController.show')
Route.get('/users', () => {
throw new Error('HttpExceptionHandler will handle this.') 👈
})
throw new Error('This error will be handled by @athenna/core.') 👈
Errors handled by @athenna/core
usually means that a
bootstrap failure has been found in your application.
Configuration
The debug
option in your
Path.config('app.ts')
./src/config/app.ts
APP_DEBUG
environment
variable, which is stored in your .env
file.
During local development, you should set the APP_DEBUG
environment variable to true
. In your production
environment, this value should always be false
. If the
value is set to true
in production, you risk exposing
sensitive configuration values to your application's end
users.
Every error will be logged by default using the console
driver from @athenna/logger
. By default, Athenna uses the
exception
channel of your
Path.config('logging.ts')
./src/config/logging.ts
You can change the driver and formatter of exception
channel inside
Path.config('logging.ts')
./src/config/logging.ts
Http exceptions
In @athenna/http
package there are exported the most
common exception that a http application might throw when
building one. These exceptions were created based on its
status code and the meaning of it:
Status code | Exception Class |
---|---|
400 | BadRequestException |
401 | UnauthorizedException |
403 | ForbiddenException |
404 | NotFoundException |
405 | MethodNotAllowedException |
406 | NotAcceptableException |
408 | RequestTimeoutException |
413 | PayloadTooLargeException |
422 | UnprocessableEntityException |
500 | InternalServerException |
501 | NotImplementedException |
502 | BadGatewayException |
503 | ServiceUnavailableException |
The HttpException
class
All of the above exceptions where created from
HttpException
class, which is the base class to create
custom http exceptions. If you need to create some http
exception from a status code that is not present above,
create it extending HttpException
:
import { HttpException } from '@athenna/http'
export class PaymentRequiredException extends HttpException {
public constructor(message = 'Payment required.') {
const status = 402
const help = undefined
const code = 'E_PAYMENT_REQUIRED_ERROR'
super({ code, help, status, message })
}
}
Ignore exceptions by status and code
You can ignore an exception from being logged if its status
code or the code does not match your requirements. To do so
you can add the following configurations to the logger
property in your
Path.config('http.ts')
./src/config/http.ts
export default {
logger: {
enabled: Env('LOG_HTTP', true),
ignoreStatuses: [404],
ignoreCodes: ['E_NOT_FOUND_ERROR']
}
}
From now on, all the exceptions thrown in your http
application will not be logged if its status is equal
to 404
or the code is E_NOT_FOUND_ERROR
.
Custom exceptions
You can create custom exception by executing the following Artisan command:
node artisan make:exception NotFoundResourceException
Next, import and raise the exception as follows.
import { NotFoundResourceException } from '#src/exceptions/NotFoundResourceException'
throw new NotFoundResourceException('Your resource has not been found.')
Always try to use a custom exception to throw your errors
inside Athenna. If you use Error
, TypeError
and other
classes, it will not be treated by the handlers and will
always be considered as a not treated exception.
Implementing your own exception handler
Let's suppose you want to write a custom logic for handling your exceptions. You can do so by creating your own exception handler:
import { type ErrorContext, HttpExceptionHandler } from '@athenna/http'
export class Handler extends HttpExceptionHandler {
public async handle(ctx: ErrorContext) {
// Implement your own logic
}
}
Now you need to register your exception handler when bootstrapping your application:
await ignite.httpServer({
exceptionHandlerPath: '#src/http/exceptions/Handler' 👈
})