Fork me on GitHub

Error handling

Even the most simplistic applications have to handle errors some way or the other. Ninja supports you by providing a default mechanism to throw exceptions and handle them via HTML views.

Ninja’s exceptions

Ninja provides four types of exceptions:

  • BadRequestException
  • ForbiddenRequestException
  • RequestNotFoundException
  • InternalServerErrorException

A BadRequestException should signal a faulty request by the user. It is similar in mindset as the HTTP error 400.

A ForbiddenRequestException should signal a unauthorized request by the user. It is similar in mindset as the HTTP error 403.

A RequestNotFoundException should signal a unauthorized request by the user. It is similar in mindset as the HTTP error 404.

An InternalServerErrorException signals that something went wrong inside your application - pretty much like the HTTP error 500.

Both exceptions are unchecked, and you can wrap your own exceptions inside them. For instance if you encounter an IOException you can rethrow that exception by calling throw new InternalServerErrorException(ioException).

At the very end of the request handling Ninja will detect the exception and render an appropriate error page.

Errors and content negotiation

The representation of the error to the user is based on content negotiation. Ninja by default properly communicates errors in HTML, JSON and XML.

HTML error representation

The default HTML views for errors can be found here:

  • views/system/400badRequest.ftl.html
  • views/system/404notFound.ftl.html
  • views/system/403forbidden.ftl.html
  • views/system/500internalServerError.ftl.html
  • views/system/401unauthorized.ftl.html (if an authorization is required)

You can overwrite the views by creating the appropriate files in your application at the very same locations (views/system/…).

This allows you to use your own styling and messages for the error views. The rendering context will contain a Message object, containing a text description of the error type, and an error message from the corresponding exception (if any).

You can also change their locations using the following ninja properties:

  • application.views.400badRequest
  • application.views.404notFound
  • application.views.403forbidden
  • application.views.500internalServerError
  • application.views.401unauthorized

JSON and XML error representations

JSON and XML errors will both be rendered by content negotiation and their default template rendering engines. Errors thus will be rendered as JSON or XML if the user sends header Accept: application/json or Accept: application/xml.

The error itself based on ninja.util.Message which contains one field called “text”.

By default the JSON error as Message will look like:

    "text": "Oops. The requested route cannot be found.",
    "error": "My exception localized message."

And XML Message looks like:

    <text>Oops. The requested route cannot be found.</text>
    <error>My exception localized message.</text>

Internationalization of errors

There are basic default error messages defined. You can define your own and translate them by adding the following keys to your conf/ files:

  • Bad request: ninja.system.bad_request.text
  • Internal server error: ninja.system.internal_server_error.text
  • Route not found: ninja.system.not_found.text

Keys and default values are defined in ninja.NinjaConstant.

Exception messages can also be defined as keys in your conf/, while the localized exception message will be used if no translation exists. So for example throw new BadRequestException(“error.invalidData”); will result in a translation of error.invalidData in your error page rendering context.


If you want to tweak Ninja’s error handling even more have a look at “custom routing”. That’s an advanced topic and explains conf.Ninja and its possibilities.