Package Exports
- error-shield
Readme
๐ก๏ธ Error Shield
Elegant, structured error handling for Node.js & Express.js
Stop writing repetitive error handling code. Error Shield gives you a battle-tested toolkit โ
custom error classes, async wrappers, Express middleware, and 40+ HTTP error creators โ out of the box.
Get Started ยท API Reference ยท Examples ยท Contributing
โจ Why Error Shield?
| Pain Point | How Error Shield Helps |
|---|---|
| โ Inconsistent error responses across routes | โ
Uniform ErrorDetails structure everywhere |
โ Boilerplate try/catch in every async handler |
โ
asyncHandler() wraps it for you |
| โ Manually setting status codes & messages | โ
40+ pre-built Errors with correct codes |
| โ No context attached to errors for debugging | โ
AppError carries structured context data |
| โ Missing TypeScript types for errors | โ Full type definitions included |
๐ฆ Installation
# npm
npm install error-shield
# yarn
yarn add error-shield
# pnpm
pnpm add error-shieldโก Quick Start
Get up and running in under 60 seconds:
const {
AppError,
handleError,
Errors,
expressErrorHandler,
asyncHandler,
} = require("error-shield");
// 1๏ธโฃ Throw meaningful errors
throw Errors.notFound("User not found", { userId: 42 });
// 2๏ธโฃ Handle & format any error
const details = handleError(new Error("Oops"), { includeStack: true });
// 3๏ธโฃ Plug into Express with one line
app.use(expressErrorHandler({ includeTimestamp: true }));That's it โ structured errors, formatted output, and Express integration with zero boilerplate. ๐
๐ Table of Contents
- Why Error Shield?
- Installation
- Quick Start
- Usage Examples
- API Reference
- Error Creators โ Full Reference
- TypeScript Support
- Contributing
- License
๐ Usage Examples
1๏ธโฃ Custom Errors with AppError
Create rich, structured errors with status codes, error codes, and arbitrary context:
const { AppError, handleError } = require("error-shield");
const error = new AppError("Something went wrong", 500, "CUSTOM_ERROR", {
userId: 123,
action: "updateProfile",
});
const errorDetails = handleError(error, {
includeStack: true,
includeTimestamp: true,
});
console.log(errorDetails);๐ Example Output
{
"message": "Something went wrong",
"statusCode": 500,
"code": "CUSTOM_ERROR",
"context": {
"userId": 123,
"action": "updateProfile"
},
"isOperational": true,
"timestamp": "2026-02-24T10:30:00.000Z",
"stack": "Error: Something went wrong\n at ..."
}2๏ธโฃ Error Creators
Use pre-built error factories for common HTTP errors โ no need to memorize status codes:
const { Errors } = require("error-shield");
// ๐ด 400 โ Bad Request
throw Errors.badRequest("Invalid input provided", { field: "email" });
// ๐ 401 โ Unauthorized
throw Errors.unauthorized("Authentication required");
// ๐ 404 โ Not Found
throw Errors.notFound("User not found", { userId: 123 });
// โ๏ธ 422 โ Validation Error
throw Errors.validationError("Email is required", { field: "email" });
// ๐ฆ 429 โ Too Many Requests
throw Errors.tooManyRequests("Rate limit exceeded", { retryAfter: 60 });
// ๐ฅ 500 โ Internal Server Error
throw Errors.internalServerError("Unexpected failure");3๏ธโฃ Express.js Middleware
Plug in a production-ready error handler with a single line:
const express = require("express");
const { expressErrorHandler, asyncHandler, Errors } = require("error-shield");
const app = express();
// Your routes โ errors are automatically caught & forwarded
app.get(
"/users/:id",
asyncHandler(async (req, res) => {
const user = await getUserById(req.params.id);
if (!user) {
throw Errors.notFound("User not found", { userId: req.params.id });
}
res.json(user);
}),
);
// โฌ๏ธ Error handler middleware (must be last)
app.use(
expressErrorHandler({
includeStack: process.env.NODE_ENV !== "production",
includeTimestamp: true,
}),
);
app.listen(3000, () => console.log("๐ Server running on port 3000"));๐ก Tip: Combine
asyncHandlerwithexpressErrorHandlerfor completely boilerplate-free async route error handling.
4๏ธโฃ Async Handler Wrapper
Eliminate try/catch blocks in your async route handlers:
const { asyncHandler } = require("error-shield");
// โ Without asyncHandler
app.get("/api/data", async (req, res, next) => {
try {
const data = await fetchData();
res.json(data);
} catch (err) {
next(err); // easy to forget!
}
});
// โ
With asyncHandler โ clean & safe
app.get(
"/api/data",
asyncHandler(async (req, res) => {
const data = await fetchData();
res.json(data);
}),
);5๏ธโฃ Custom Logger
Attach your own logging logic โ send errors to Sentry, Datadog, or any external service:
const { handleError } = require("error-shield");
const errorDetails = handleError(error, {
logger: (details) => {
console.error("[ERROR]", details.message);
// ๐ค Send to your logging service
Sentry.captureException(details);
},
});๐ API Reference
AppError class
Extends the native
Errorclass with structured metadata.
class AppError extends Error {
code?: string;
statusCode?: number;
context?: Record<string, any>;
isOperational: boolean;
}| Parameter | Type | Default | Description |
|---|---|---|---|
message |
string |
โ | Error message |
statusCode |
number |
500 |
HTTP status code |
code |
string |
โ | Machine-readable error code |
context |
Record<string, any> |
โ | Additional debugging context |
formatError(error, options?)
Formats any error into a consistent
ErrorDetailsobject.
| Parameter | Type | Description |
|---|---|---|
error |
Error | AppError |
The error to format |
options |
ErrorHandlerOptions |
Formatting options |
Returns: ErrorDetails
handleError(error, options?)
Handles errors with optional logging and formatting.
| Parameter | Type | Description |
|---|---|---|
error |
Error | AppError |
The error to handle |
options |
ErrorHandlerOptions |
Handler options (includes logger, includeStack, includeTimestamp) |
Returns: ErrorDetails
asyncHandler(fn)
Wraps an async Express route handler to automatically catch rejected promises.
| Parameter | Type | Description |
|---|---|---|
fn |
(req, res, next) => Promise<any> |
Async route handler function |
Returns: Wrapped Express middleware function
expressErrorHandler(options?)
Creates an Express.js error-handling middleware.
| Parameter | Type | Description |
|---|---|---|
options |
ErrorHandlerOptions |
Handler options |
Returns: Express error middleware (err, req, res, next) => void
๐๏ธ Error Creators โ Full Reference
Pre-built factory methods for all standard HTTP error codes. Every method returns an AppError instance.
// Signature for all creators:
Errors.methodName(message?, context?)
// โ Returns: AppError๐ 4xx Client Errors (click to expand)
| Method | Code | Default Message |
|---|---|---|
badRequest(message, context?) |
400 |
(required) |
unauthorized(message?, context?) |
401 |
Unauthorized |
paymentRequired(message?, context?) |
402 |
Payment Required |
forbidden(message?, context?) |
403 |
Forbidden |
notFound(message?, context?) |
404 |
Not Found |
methodNotAllowed(message?, context?) |
405 |
Method Not Allowed |
notAcceptable(message?, context?) |
406 |
Not Acceptable |
proxyAuthRequired(message?, context?) |
407 |
Proxy Authentication Required |
requestTimeout(message?, context?) |
408 |
Request Timeout |
conflict(message, context?) |
409 |
(required) |
gone(message?, context?) |
410 |
Gone |
lengthRequired(message?, context?) |
411 |
Length Required |
preconditionFailed(message?, context?) |
412 |
Precondition Failed |
payloadTooLarge(message?, context?) |
413 |
Payload Too Large |
uriTooLong(message?, context?) |
414 |
URI Too Long |
unsupportedMediaType(message?, context?) |
415 |
Unsupported Media Type |
rangeNotSatisfiable(message?, context?) |
416 |
Range Not Satisfiable |
expectationFailed(message?, context?) |
417 |
Expectation Failed |
imATeapot(message?, context?) |
418 |
I'm a Teapot |
misdirectedRequest(message?, context?) |
421 |
Misdirected Request |
unprocessableEntity(message?, context?) |
422 |
Unprocessable Entity |
validationError(message, context?) |
422 |
(required) |
locked(message?, context?) |
423 |
Locked |
failedDependency(message?, context?) |
424 |
Failed Dependency |
tooEarly(message?, context?) |
425 |
Too Early |
upgradeRequired(message?, context?) |
426 |
Upgrade Required |
preconditionRequired(message?, context?) |
428 |
Precondition Required |
tooManyRequests(message?, context?) |
429 |
Too Many Requests |
requestHeaderFieldsTooLarge(message?, context?) |
431 |
Request Header Fields Too Large |
unavailableForLegalReasons(message?, context?) |
451 |
Unavailable For Legal Reasons |
๐ด 5xx Server Errors (click to expand)
| Method | Code | Default Message |
|---|---|---|
internalServerError(message?, context?) |
500 |
Internal Server Error |
notImplemented(message?, context?) |
501 |
Not Implemented |
badGateway(message?, context?) |
502 |
Bad Gateway |
serviceUnavailable(message?, context?) |
503 |
Service Unavailable |
gatewayTimeout(message?, context?) |
504 |
Gateway Timeout |
httpVersionNotSupported(message?, context?) |
505 |
HTTP Version Not Supported |
variantAlsoNegotiates(message?, context?) |
506 |
Variant Also Negotiates |
insufficientStorage(message?, context?) |
507 |
Insufficient Storage |
loopDetected(message?, context?) |
508 |
Loop Detected |
bandwidthLimitExceeded(message?, context?) |
509 |
Bandwidth Limit Exceeded |
notExtended(message?, context?) |
510 |
Not Extended |
networkAuthenticationRequired(message?, context?) |
511 |
Network Authentication Required |
networkConnectTimeout(message?, context?) |
599 |
Network Connect Timeout |
๐ฆ TypeScript Support
Error Shield ships with full TypeScript declarations โ zero extra config needed.
import {
AppError,
Errors,
handleError,
asyncHandler,
expressErrorHandler,
type ErrorDetails,
type ErrorHandlerOptions,
} from "error-shield";
// Fully typed error creation
const error: AppError = Errors.notFound("User not found", {
userId: 42,
});
// Typed error details
const details: ErrorDetails = handleError(error, {
includeStack: true,
includeTimestamp: true,
});๐ค Contributing
Contributions, issues, and feature requests are welcome!
- Fork the repository
- Create your feature branch โ
git checkout -b feature/amazing-feature - Commit your changes โ
git commit -m "feat: add amazing feature" - Push to the branch โ
git push origin feature/amazing-feature - Open a Pull Request
๐ License
This project is licensed under the ISC License.
Made with โค๏ธ by Gopinath Kathirvel
โญ If you found this useful, give it a star on GitHub! โญ