You are viewing the legacy version of AdonisJS. Visit for newer docs. This version will receive security patches until the end of 2021.

Upgrading from 4.0

The 4.1 release contains a number of bug fixes and API improvements to keep the code base simple and less magical. Breaking changes were kept to a minimum, however, they could not be eliminated entirely.

Getting started

The first step is to update all dependencies.

We use npm-check to pull the latest versions of packages:

> npm install -g npm-check

Run the following command to update dependencies interactively:

> npm-check -u

Exception handling

One of the most significant changes has been to the global exception handler.

If you never created the global exception handler, feel free to ignore this section.

Make the following changes to the app/Exceptions/Handler.js file.

  1. Ensure your exception handler extends the BaseExceptionHandler:

    const BaseExceptionHandler = use('BaseExceptionHandler')
    class ExceptionHandler extends BaseExceptionHandler {
  2. Call super.handle for exceptions you don’t want to handle:

    class ExceptionHandler extends BaseExceptionHandler {
      async handle (error, { response }) {
        if ( === 'UserNotFoundException') {
          // handle it yourself
  3. Lastly, you can remove Exception.bind calls from your codebase, since all exceptions will be routed to the global exception handler.



Route.url generates a fully qualified URL to a pre-registered route.

Previously, domain was passed as a string literal.

domain is now accepted as an object.


Route.url('posts/:id', { id: 1 }, '')


Route.url('posts/:id', { id: 1 }, { domain: '' })


The validator provider now uses the latest version of Indicative, causing the following breaking changes.


There concept of named formatters no longer exists.

If you want to use a pre-existing formatter, instead of passing by name, you must now pass by reference.


const { validate } = use('Validator')
validate(data, rules, messages, 'jsonapi')


const { validate, formatters } = use('Validator')
validate(data, rules, messages, formatters.JsonApi)

The same applies to route validators too.


class StoreUser {
  get formatter () {
    return 'jsonapi'


const { formatters } = use('Validator')

class StoreUser {
  get formatter () {
    return formatters.JsonApi


The new version of Indicative exposes the configure method to define library-wide defaults:

const { formatters, configure } = use('Validator')

  FORMATTER: formatters.JsonApi



The css global has been changed to style. The css global is no longer supported


{{ css('style') }}


{{ style('style') }}


Previously, date formatting was inconsistent with newly created records and existing records.

This has been fixed in the newer release with a small breaking change (make sure to read the related issue).


The date fields no longer cast to moment instances on the model instance.


const user = await User.find(1)
user.created_at instanceof moment // true


const user = await User.find(1)
user.created_at instanceof moment // false

This change prevents you from mutating the date on the model instance directly and instead use the castDates hook to mutate the date when you serialize model properties.

The castDates hook works as it did previously:

class User extends Model {
  static castDates (field, value) {
    if (field === 'dob') {
      return `${value.fromNow(true)} old`
    return super.formatDates(field, value)


A number of bug fixes have been applied to keep the codebase reliable.

Also, a handful of performance improvements have been implemented.


Since Indicative is rewritten from the ground up, the new version is 2x faster than it was previously.


Middleware is now resolved by the middleware parsing layer at the time of booting the app, instantiating a new instance of them for each request (previously, the resolve process was used for each request).

Better errors

Errors will now appear nicely formatted in your terminal as shown below: