JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 10
  • Score
    100M100P100Q37516F
  • License ISC

Comprehensive error handling utility for Node.js & Express.js โ€” custom error classes, async handler wrapper, Express middleware, HTTP error creators, retry logic, error chaining, and TypeScript support.

Package Exports

  • error-shield

Readme

๐Ÿ›ก๏ธ Error Shield

Elegant, structured error handling for Node.js & Express.js

npm version License TypeScript Node.js Downloads

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


๐Ÿš€ 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 asyncHandler with expressErrorHandler for 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 Error class 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 ErrorDetails object.

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!

  1. Fork the repository
  2. Create your feature branch โ€” git checkout -b feature/amazing-feature
  3. Commit your changes โ€” git commit -m "feat: add amazing feature"
  4. Push to the branch โ€” git push origin feature/amazing-feature
  5. 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! โญ