Skip to main content

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:

Path.routes('http.ts')
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.') 👈
info

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') configuration file determines how much information about an error is actually displayed to the user. By default, this option is set to respect the value of the 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') file to log all exceptions that happens in your application.

tip

You can change the driver and formatter of exception channel inside Path.config('logging.ts') file. This way you can send all your error logs to another provider and with a different formatter.

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 codeException Class
400BadRequestException
401UnauthorizedException
403ForbiddenException
404NotFoundException
405MethodNotAllowedException
406NotAcceptableException
408RequestTimeoutException
413PayloadTooLargeException
422UnprocessableEntityException
500InternalServerException
501NotImplementedException
502BadGatewayException
503ServiceUnavailableException

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') configuration file:

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 '#app/exceptions/NotFoundResourceException'

throw new NotFoundResourceException('Your resource has not been found.')
tip

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:

app/http/exceptions/Handler.ts
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:

Path.bootstrap('main.ts')
await ignite.httpServer({
exceptionHandlerPath: '#app/http/exceptions/Handler' 👈
})