next(err) with a non-falsy value, the error skips all remaining normal handlers and flows to the nearest downstream error handler — a function with the signature (err, req, res, next). You can register one global error handler on the app, one per sub-router, or both.
BlazeError
BlazeError is Blaze’s built-in structured error class. Throw it anywhere in your handler stack to produce a deterministic HTTP error response with a status code, a message, and an optional meta bag that the error handler can spread into the JSON body.
number
required
The HTTP status code to send in the response (e.g.
400, 401, 403, 404, 422, 500).string
required
A human-readable error message included in the response body.
Record<string, unknown>
Optional bag of additional fields spread into the JSON error response. Useful for machine-readable error codes, field-level validation errors, etc.
BlazeError extends Error and maintains a proper prototype chain, so
err instanceof BlazeError works correctly in all environments — including
after transpilation.Global error handler
app.onError() registers a single global error boundary. Register it after all your routes and middleware so it catches errors from the entire app. The 4-argument signature — (err, req, res, next) — is what tells Blaze this is an error handler rather than a regular middleware.
Route-level error boundaries
Sub-routers can register their own error handlers withrouter.onError(). These catch errors thrown within that router’s layer stack. You can handle specific error types locally and bubble the rest to the global handler by calling next(err).
Async error propagation
Blaze wraps every handler call so that rejected Promises are automatically forwarded tonext(err). You do not need to write try/catch blocks in most handlers — Blaze catches uncaught async errors for you.
The only case where you need an explicit
next(err) call is in
synchronous middleware that conditionally forwards an error rather than
throwing — for example, conditional auth logic that calls next(err) when
validation fails and next() when it succeeds.Error flow summary
1
Handler throws or calls next(err)
Any thrown error (sync or async) in a route or middleware is caught by Blaze’s layer wrapper and forwarded to the routing engine as
next(err).2
Normal layers are skipped
The router skips all remaining normal
(req, res, next) handlers — they are not called while an error is in flight.3
First matching error handler is called
The router finds the first Layer with a 4-argument function (
(err, req, res, next)) downstream of where the error originated and invokes it.4
Error handler calls next(err) to bubble
If the error handler can’t handle a particular error type, it calls
next(err) again to pass the error to the next downstream error handler — typically the global one on app.5
Global handler responds
app.onError() is the last stop. If it calls next(err) or throws, Blaze returns a bare 500 response.