Since an ExceptionHandlerExceptionHandler is a partial function, it can choose which exceptions it would like to handle and which not. Unhandled exceptions will simply continue to bubble up in the route structure. At the root of the route tree any still unhandled exception will be dealt with by the top-level handler which always handles all exceptions.

Route.seal internally wraps its argument route with the handleExceptions directive in order to “catch” and handle any exception.

In the first case your handler will be “sealed” (which means that it will receive the default handler as a fallback for all cases your handler doesn’t handle itself) and used for all exceptions that are not handled within the route structure itself.

The second case allows you to restrict the applicability of your handler to certain branches of your route structure.

Distinguishing between errors and failures (i.e. thrown Exceptions handled via the ExceptionHandlerExceptionHandler) provides a much better mental model but also leads to performance improvements.

This is because exceptions are known to have a negative performance impact for cases when the depth of the call stack is significant (stack trace construction cost) and when the handler is located far from the place of the throwable instantiation (stack unwinding costs).

In a typical Akka application both these conditions are frequently true, so as a rule of thumb, you should try to minimize the number of Throwable instances reaching the exception handler.

Respond with headers and Exception Handler

If you wrap an ExceptionHandler inside a different directive, then that directive will still apply. Example below shows that wrapping an ExceptionHandler inside a respondWithHeader directive will still add the header to the response.