-
Notifications
You must be signed in to change notification settings - Fork 0
Error Handling
Tanzim Hossain edited this page Apr 28, 2026
·
4 revisions
NextRush provides a structured HTTP error hierarchy in @nextrush/errors (re-exported from nextrush).
Error
└── HttpError / NextRushError (base)
├── 4xx Client Errors
│ ├── BadRequestError (400)
│ ├── UnauthorizedError (401)
│ ├── PaymentRequiredError (402)
│ ├── ForbiddenError (403)
│ ├── NotFoundError (404)
│ ├── MethodNotAllowedError (405)
│ ├── NotAcceptableError (406)
│ ├── ProxyAuthRequiredError (407)
│ ├── RequestTimeoutError (408)
│ ├── ConflictError (409)
│ ├── GoneError (410)
│ ├── LengthRequiredError (411)
│ ├── PreconditionFailedError (412)
│ ├── PayloadTooLargeError (413)
│ ├── UriTooLongError (414)
│ ├── UnsupportedMediaTypeError (415)
│ ├── RangeNotSatisfiableError (416)
│ ├── ExpectationFailedError (417)
│ ├── ImATeapotError (418)
│ ├── UnprocessableEntityError (422)
│ ├── LockedError (423)
│ ├── FailedDependencyError (424)
│ ├── TooEarlyError (425)
│ ├── UpgradeRequiredError (426)
│ ├── PreconditionRequiredError (428)
│ ├── TooManyRequestsError (429)
│ ├── RequestHeaderFieldsTooLargeError (431)
│ └── UnavailableForLegalReasonsError (451)
└── 5xx Server Errors
├── InternalServerError (500)
├── NotImplementedError (501)
├── BadGatewayError (502)
├── ServiceUnavailableError (503)
├── GatewayTimeoutError (504)
├── HttpVersionNotSupportedError (505)
├── VariantAlsoNegotiatesError (506)
├── InsufficientStorageError (507)
├── LoopDetectedError (508)
├── NotExtendedError (510)
└── NetworkAuthRequiredError (511)
import { NotFoundError, BadRequestError, UnauthorizedError } from 'nextrush';
router.get('/users/:id', async (ctx) => {
const user = await db.findUser(ctx.params.id);
if (!user) {
throw new NotFoundError('User not found');
}
ctx.json(user);
});
router.post('/users', async (ctx) => {
const { name, email } = ctx.body as { name?: string; email?: string };
if (!name || !email) {
throw new BadRequestError('name and email are required');
}
ctx.status = 201;
ctx.json(await db.createUser({ name, email }));
});All HTTP errors accept an options object:
throw new BadRequestError('Validation failed', {
code: 'VALIDATION_ERROR', // machine-readable error code
expose: true, // expose message to client (default for 4xx)
details: { field: 'email', reason: 'invalid format' },
cause: originalError, // wraps the original error
});-
4xx errors:
expose: trueby default — the message is sent to the client -
5xx errors:
expose: falseby default — message is replaced with'Internal Server Error'
This prevents leaking internal paths, SQL queries, or stack traces to clients.
Shorthand functions for common errors:
import {
notFound, badRequest, unauthorized, forbidden, conflict,
unprocessableEntity, tooManyRequests, internalError,
methodNotAllowed, badGateway, serviceUnavailable, gatewayTimeout,
createError, isHttpError, getErrorStatus, getSafeErrorMessage
} from 'nextrush';
throw notFound('User not found');
throw badRequest('Invalid input');
throw unauthorized('Token expired');
throw forbidden('Insufficient permissions');
// Generic factory
throw createError(418, "I'm a teapot");
// Check if an error is an HttpError
if (isHttpError(err)) {
console.log(err.status); // 404, 400, etc.
}import { ValidationError } from '@nextrush/errors';
throw new ValidationError('Input validation failed', {
issues: [
{ field: 'email', message: 'Invalid email format' },
{ field: 'age', message: 'Must be a number' },
]
});Specific validation error classes:
import {
RequiredFieldError,
TypeMismatchError,
RangeValidationError,
LengthError,
PatternError,
InvalidEmailError,
InvalidUrlError,
} from '@nextrush/errors';const app = createApp();
app.setErrorHandler((error, ctx) => {
if (error instanceof ValidationError) {
ctx.status = 400;
ctx.json({ error: error.message, details: error.details });
return;
}
if (error instanceof UnauthorizedError) {
ctx.status = 401;
ctx.json({ error: 'Please log in' });
return;
}
ctx.status = 500;
ctx.json({ error: 'Something went wrong' });
});import { errorHandler } from 'nextrush';
// Register before routes to catch all errors
app.use(errorHandler({
includeStack: process.env.NODE_ENV !== 'production',
logger: (err, ctx) => myLogger.error({ err, path: ctx.path }),
handlers: new Map([
[ValidationError, (err, ctx) => {
ctx.status = 422;
ctx.json({ errors: err.details });
}],
]),
}));Register after all routes to handle unmatched requests:
import { notFoundHandler } from 'nextrush';
// Routes ...
app.route('/api', router);
// Catch-all 404
app.use(notFoundHandler('The requested resource was not found'));Every HttpError instance has:
| Property | Type | Description |
|---|---|---|
status |
number |
HTTP status code |
message |
string |
Error message |
code |
string |
Machine-readable error code |
expose |
boolean |
Whether to send message to client |
details |
Record<string, unknown> | undefined |
Additional error details |
cause |
unknown |
Original error that caused this one |
NextRush · MIT License · Docs · Issues