Exception Handling

Exception Handling

Exceptions thrown during route execution bubble up through the route structure to the next enclosing handleExceptions directive, Route.seal or the onFailure callback of a future created by detach.

Similarly to the way that Rejections are handled the handleExceptions directive delegates the actual job of converting a list of rejections to its argument, an ExceptionHandler, which is defined like this:

trait ExceptionHandler extends PartialFunction[Throwable, Route]

runRoute defined in HttpService does the same but gets its ExceptionHandler instance implicitly.

Since an ExceptionHandler 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. The top-most ExceptionHandler applied by runRoute will handle all exceptions that reach it.

So, if you'd like to customize the way certain exceptions are handled simply bring a custom ExceptionHandler into implicit scope of runRoute or pass it to an explicit handleExceptions directive that you have put somewhere into your route structure.

Here is an example:

import akka.http.model.HttpResponse
import akka.http.model.StatusCodes._
import akka.http.server._
import Directives._

implicit def myExceptionHandler =
  ExceptionHandler {
    case e: ArithmeticException =>
      extractUri { uri =>
        logWarning(s"Request to $uri could not be handled normally")
        complete(HttpResponse(InternalServerError, entity = "Bad numbers, bad result!!!"))

object MyApp {
  implicit val system = ActorSystem()
  import system.dispatcher
  implicit val materializer = FlowMaterializer()

  def handler = Route.handlerFlow(`<my-route-definition>`)