Aura Router

Catching Errors

The onError handler captures all errors arising from route handlers, endpoint middlewares, global middlewares, and internal router logic. This provides a centralized mechanism for customizing error responses and adding diagnostics.

import { createRouter, isRouterError, type RouterConfig } from "@aura-stack/router"

const onErrorHandler: RouterConfig["onError"] = (error, request) => {
  const message = isRouterError(error) ? "Unexpected Internal Error" : `The error was caused by ${error.message}`
  return Response.json({ message })
}

Internal router errors are instances of the RouterError class. The isRouterError(error) helper function effectively detects and handles them.


Overview


Key Concepts

  • All errors occurring within the router logic are intercepted by the onError handler. Common sources include:
    • Global middlewares
    • Endpoint middlewares
    • Route handlers
    • Internal errors (e.g., bad requests, configuration issues, validation mismatches)

Type Inference

The onError handler receives an error argument of type Error | RouterError. The isRouterError function narrows the type to access router-specific fields such as status and statusText.

Relevant Types:

  • RouterConfig
  • RouterError

Usage

Basic Usage

The onError handler can be passed directly to the createRouter function.

import { createRouter } from "@aura-stack/router"

export const router = createRouter([], {
  onError: (error, request) => {
    console.error("Router error:", error)
    return Response.json({ message: "Internal Server Error" }, { status: 500 })
  },
})

Using RouterConfig Type

Defining the handler using RouterConfig["onError"] improves clarity and reusability.

import { createRouter, type RouterConfig } from "@aura-stack/router"

const onErrorHandler: RouterConfig["onError"] = (error, request) => {
  console.error("Router error:", error)
  return Response.json({ message: "Internal Server Error" }, { status: 500 })
}

export const router = createRouter([], {
  onError: onErrorHandler,
})

Advanced Usage

For more complex scenarios, custom error classes and structured responses can be implemented.

import { createRouter, isRouterError, statusCode, type RouterConfig } from "@aura-stack/router"

class LoginError extends Error {}

interface ErrorResponse {
  message: string
  details: string
  cause: string
}

const onErrorHandler: RouterConfig["onError"] = (error, request) => {
  if (isRouterError(error)) {
    const { message, name, stack, status, statusText } = error

    const response: ErrorResponse = {
      message,
      cause: stack ?? "",
      details: `The error was caused by ${name} in ${stack ?? "unknown"}`,
    }

    return Response.json(response, {
      status,
      statusText,
    })
  }
  const response: ErrorResponse = {
    message: error instanceof LoginError ? "The error was caused in 'Login Form'" : "Bad Request",
    details: error.message,
    cause: error.stack ?? "",
  }
  return Response.json(response, { status: statusCode.BAD_REQUEST })
}

export const router = createRouter([], {
  onError: onErrorHandler,
})

On this page