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
onErrorhandler. 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:
RouterConfigRouterError
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,
})