Skip to main content

Error Handling

Understand how you can handle the errors of the CLI 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.

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 CLI application, which means that only errors that happens inside the handle() method of commands and bellow that will be handled:

app/console/commands/AppCommand.ts
import { BaseCommand } from '@athenna/artisan'
import { AppService } from '#app/services/AppService'

export class AppCommand extends BaseCommand {
public static signature(): string {
return 'app'
}

public static description(): string {
throw new Error('This error will be handled by @athenna/core.') 👈

return `Get some information's about the application.`
}

public async handle(): Promise<void> {
const appService = ioc.safeUse<AppService>('App/Services/AppService')
const json = JSON.stringify(appService.findOne(), null, 2)

throw new Error('ConsoleExceptionHandler will handle this error.') 👈

this.logger.info(`Application information's: ${json}`)
}
}
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.

Custom exceptions

You can create custom exception by executing the following Artisan command:

node artisan make:exception BadCommandException

Next, import and raise the exception as follows.

import { BadCommandException } from '#app/exceptions/BadCommandException'

throw new BadCommandException('Your command is bad.')
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.

Simple exceptions

When talking about exceptions in Artisan and CLI applications, we can divide them into two categories: simple exceptions and the more complex ones. Simple exceptions are exceptions that when handled by the ConsoleExceptionHandler will only log the exception message. The more complex will log the entire exception including code, message, help and stack trace.

Simple exceptions are recognized by ConsoleExceptionHandler by the code. If the code is E_SIMPLE_CLI, it will be considered as a simple exception:

app/console/exceptions/NotFoundDatabaseExceptio.ts
import { Exception } from '@athenna/common'

export class NotFoundDatabaseException extends Exception {
public constructor(databaseName: string) {
const code = 'E_SIMPLE_CLI' 👈

super({ code, message: `Database ${databaseName} not found.` })
}
}

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/console/exceptions/Handler.ts
import { ConsoleExceptionHandler } from '@athenna/artisan'

export class Handler extends ConsoleExceptionHandler {
public async handle(error: any) {
// Implement your own logic
}
}

Now you need to register your exception handler when bootstrapping your application:

Path.bootstrap('main.ts')
await ignite.console(process.argv, {
displayName: 'Athenna',
exceptionHandlerPath: '#app/console/exceptions/Handler', 👈
})