The @nodeboot/error package provides the built-in exception hierarchy used across Node-Boot.
It gives you a small set of reusable HTTP-aware error classes for controller and service code, plus framework-level exceptions used during:
- request parameter binding
- JSON/body parsing
- authorization checks
- current-user resolution
- global error serialization
When you throw an HttpError (or any subclass), Node-Boot drivers use its httpCode to set the HTTP response status automatically.
✅ HTTP-aware base class via HttpError
✅ Ready-made 4xx/5xx exceptions for common API responses
✅ Authorization errors for @Authorized() and @CurrentUser flows
✅ Parameter binding errors for invalid, missing, or malformed input
✅ Framework integration with Node-Boot's global error handling across Express, Fastify, Koa, native HTTP, Ghost, and Lambda
✅ Customizable serialization through custom error handlers or toJSON()
pnpm add @nodeboot/errorimport {
AccessDeniedError,
AuthorizationCheckerNotDefinedError,
AuthorizationRequiredError,
BadRequestError,
CurrentUserCheckerNotDefinedError,
ForbiddenError,
HttpError,
InternalServerError,
InvalidParamError,
MethodNotAllowedError,
NotAcceptableError,
NotFoundError,
ParameterParseJsonError,
ParamRequiredError,
UnauthorizedError,
} from "@nodeboot/error";The repository samples use NotFoundError for missing resources and HttpError directly for custom statuses such as 409 Conflict.
import {HttpError, NotFoundError} from "@nodeboot/error";
export class UserService {
async findUserById(userId: number) {
const user = await this.userRepository.findOneBy({id: userId});
if (!user) {
throw new NotFoundError("User doesn't exist");
}
return user;
}
async createUser(userData: CreateUserDto) {
const existingUser = await this.userRepository.findOneBy({
email: userData.email,
});
if (existingUser) {
throw new HttpError(409, `This email ${userData.email} already exists`);
}
return this.userRepository.save(userData);
}
}This matches how the sample applications protect routes with @Authorized() while letting services throw HttpError subclasses.
import {Body, Controller, Get, Param, Post} from "@nodeboot/core";
import {Authorized} from "@nodeboot/authorization";
@Controller("/users", "v1")
export class UserController {
constructor(private readonly userService: UserService) {}
@Get("/:id")
async getUserById(@Param("id") userId: number) {
return this.userService.findUserById(userId);
}
@Post("/")
@Authorized()
async createUser(@Body() userData: CreateUserDto) {
return this.userService.createUser(userData);
}
}If you register a custom @ErrorHandler(), you can transform HttpError objects before they are written to the response.
import {ErrorHandler} from "@nodeboot/core";
import {Action, ErrorHandlerInterface} from "@nodeboot/context";
import {HttpError} from "@nodeboot/error";
import {Request, Response} from "express";
@ErrorHandler()
export class ErrorMiddleware implements ErrorHandlerInterface<HttpError, Request, Response> {
async onError(error: HttpError, action: Action<Request, Response>): Promise<void> {
const status = error.httpCode || 500;
action.response.status(status).json({
message: error.message,
statusCode: error.httpCode,
});
}
}If you do not register a custom handler, Node-Boot's default global error handler serializes errors to JSON using the error name, message, and any extra enumerable properties.
| Export | Extends | HTTP status | Typical use |
|---|---|---|---|
HttpError |
Error |
custom | Base class for arbitrary HTTP responses such as new HttpError(409, "Conflict"). |
BadRequestError |
HttpError |
400 | Generic invalid request/input error. |
UnauthorizedError |
HttpError |
401 | Authentication is required or invalid. |
ForbiddenError |
HttpError |
403 | Request is authenticated but not allowed. |
NotFoundError |
HttpError |
404 | Resource does not exist. |
MethodNotAllowedError |
HttpError |
405 | HTTP method is not allowed for the target operation. |
NotAcceptableError |
HttpError |
406 | Response cannot satisfy the requested format/constraints. |
InternalServerError |
HttpError |
500 | Generic internal framework/application error. |
AccessDeniedError |
ForbiddenError |
403 | Thrown when @Authorized() denies access. |
AuthorizationRequiredError |
UnauthorizedError |
401 | Thrown when @CurrentUser or an authorization flow requires authentication. |
AuthorizationCheckerNotDefinedError |
InternalServerError |
500 | @Authorized() is used, but no authorizationChecker is configured. |
CurrentUserCheckerNotDefinedError |
InternalServerError |
500 | @CurrentUser is used, but no currentUserChecker is configured. |
ParamRequiredError |
BadRequestError |
400 | A required route/body/query/header/file/session/cookie parameter is missing. |
ParameterParseJsonError |
BadRequestError |
400 | A string parameter expected to contain JSON cannot be parsed. |
InvalidParamError |
BadRequestError |
400 | A parameter cannot be normalized into the requested target type. |
Note:
InvalidParamErroris exported under that class name, but itsnameproperty is set to"ParamNormalizationError".
Node-Boot uses this package internally during authorization checks:
AccessDeniedError→ when@Authorized()fails for the current requestAuthorizationCheckerNotDefinedError→ when@Authorized()is used without anauthorizationCheckerAuthorizationRequiredError→ when a current user is required but unavailableCurrentUserCheckerNotDefinedError→ when@CurrentUseris used without acurrentUserChecker
These errors are created by the framework drivers and parameter handlers, so in many cases you do not need to throw them manually.
@nodeboot/error is also used internally by Node-Boot's action parameter pipeline:
ParamRequiredErroris thrown when a required parameter is missingInvalidParamErroris thrown when a primitive value cannot be converted to the declared typeParameterParseJsonErroris thrown when JSON parsing fails for object/array-style inputBadRequestErroris also used for validation failures after request transformation/validation
This means controller signatures such as @Param("id") userId: number automatically participate in consistent 400-level error handling.
Across the built-in Node-Boot drivers, the flow is consistent:
- A controller/service throws an
HttpError(or subclass). - The active driver reads
error.httpCodeand applies it to the HTTP response. - If a custom
@ErrorHandler()is registered, it gets the first chance to shape the response. - Otherwise, Node-Boot's default
GlobalErrorHandlerserializes the error object.
By default, serialized errors include:
namemessage- any extra enumerable properties you added
The default serializer omits stack traces and does not include httpCode in the JSON body for HttpError instances.
If your error class implements toJSON(), that result is used instead.
- This package has no runtime dependencies listed in its
package.json. - It is intended to be used by both application code and Node-Boot internals.
- Use
HttpErrorwhen you need a status code not covered by the built-in subclasses.
MIT