Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/juanjh1/asimilation/llms.txt

Use this file to discover all available pages before exploring further.

The error handler middleware provides centralized error handling for your application, catching exceptions and returning properly formatted error responses to clients.

What It Does

The error handler middleware:
  • Catches errors thrown in route handlers and other middleware
  • Logs errors to the console for debugging
  • Returns a standardized error response to the client
  • Sends a 500 Internal Server Error status code by default
  • Prevents server crashes from unhandled exceptions

How It Works

The error handler wraps the middleware chain in a try-catch block:
import { MiddlewarePipeline } from "../../core/middleware-manager.js";
import { ArgumentedIncomingMessageAbc } from "../../abstract/abstract_req.js";
import { ArgumentedServerResponseAbc } from "../../abstract/abstract_res.js";

MiddlewarePipeline.addMiddleware(
    (req, res, next) => {
        try {
            next();
        } catch (error) {
            console.log(error);
            res.sendJson({ message: 'Internal Server error' }, 500);
        }
    }
);

Error Response Format

When an error is caught, the middleware returns a JSON response:
{
    "message": "Internal Server error"
}
HTTP Status: 500 Internal Server Error

Key Features

1
Error Logging
2
All caught errors are logged to the console, helping you debug issues:
3
console.log(error);
4
Standardized Response
5
The middleware ensures all errors result in a consistent JSON response format, making it easier for clients to handle errors.
6
Server Protection
7
By catching exceptions, the middleware prevents your server from crashing due to unhandled errors.

Enabling the Error Handler

The error handler is part of the default middleware stack. Import it to enable:
import "asimilation/default/middleware/error-handling";
import { asi, url } from "@asimilation/core";

// Define routes
url.get("/", (req, res) => {
    throw new Error("Something went wrong!");
    // This error will be caught and handled
});

asi.setup(3000, "");
asi.run();

Content Negotiation

Asimilation includes helper functions for advanced error response handling based on the Accept header. The createErrorResponseHandler function allows you to return different formats based on client preferences:
import { createErrorResponseHandler } from "asimilation/helpers/error-response";

const errorHandler = createErrorResponseHandler({
    "application/json": (res, message, statusCode) => {
        res.sendJson({ error: message }, statusCode);
    },
    "text/plain": (res, message, statusCode) => {
        res.writeHead(statusCode, { "Content-Type": "text/plain" });
        res.end(message);
    },
    "text/html": (res, message, statusCode) => {
        res.writeHead(statusCode, { "Content-Type": "text/html" });
        res.end(`<html><body><h1>Error ${statusCode}</h1><p>${message}</p></body></html>`);
    }
});

// Use in middleware
MiddlewarePipeline.addMiddleware((req, res, next) => {
    try {
        next();
    } catch (error) {
        console.error(error);
        errorHandler(req, res, 500, "Internal Server Error");
    }
});

How Content Negotiation Works

1
Parse Accept Header
2
The createErrorResponseHandler parses the client’s Accept header to determine preferred response formats.
3
Sort by Quality
4
Formats are sorted by their quality values (q parameter), with higher quality values prioritized:
5
Accept: application/json;q=0.9, text/html;q=1.0, text/plain;q=0.8
6
Match to Available Formats
7
The handler matches the client’s preferences to the formats you’ve configured.
8
Fallback to JSON
9
If no match is found or no Accept header is present, the handler defaults to JSON.

Customization

You can create custom error handling middleware with additional features:

Custom Error Response

import { MiddlewarePipeline } from "@asimilation/core";

MiddlewarePipeline.addMiddleware((req, res, next) => {
    try {
        next();
    } catch (error) {
        console.error("Error occurred:", error);
        
        res.sendJson({
            error: "Internal Server Error",
            message: error.message,
            timestamp: new Date().toISOString(),
            path: req.url
        }, 500);
    }
});

Status Code Based on Error Type

class ValidationError extends Error {
    statusCode = 400;
}

class NotFoundError extends Error {
    statusCode = 404;
}

class UnauthorizedError extends Error {
    statusCode = 401;
}

MiddlewarePipeline.addMiddleware((req, res, next) => {
    try {
        next();
    } catch (error) {
        console.error(error);
        
        const statusCode = error.statusCode || 500;
        const message = error.message || "Internal Server Error";
        
        res.sendJson({ error: message }, statusCode);
    }
});

Environment-Based Error Details

const isDevelopment = process.env.NODE_ENV === "development";

MiddlewarePipeline.addMiddleware((req, res, next) => {
    try {
        next();
    } catch (error) {
        console.error(error);
        
        const errorResponse: any = {
            error: "Internal Server Error"
        };
        
        // Only include stack trace in development
        if (isDevelopment) {
            errorResponse.message = error.message;
            errorResponse.stack = error.stack;
        }
        
        res.sendJson(errorResponse, 500);
    }
});

HTTP Status Codes

When customizing error handling, use appropriate HTTP status codes:
Status CodeMeaningUse Case
400Bad RequestInvalid input or validation errors
401UnauthorizedMissing or invalid authentication
403ForbiddenAuthenticated but not authorized
404Not FoundResource doesn’t exist
409ConflictResource conflict (e.g., duplicate)
422Unprocessable EntityValid syntax but semantic errors
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected server errors
502Bad GatewayUpstream service error
503Service UnavailableServer overloaded or maintenance
504Gateway TimeoutUpstream service timeout

Best Practices

Security Considerations:
  • Never expose stack traces in production
  • Avoid leaking sensitive information in error messages
  • Log detailed errors server-side but send generic messages to clients
  • Use error codes or types instead of exposing internal details
Structured Error Logging:Consider using a structured logging library like Winston or Pino for better error tracking:
import winston from "winston";

const logger = winston.createLogger({
    level: "error",
    format: winston.format.json(),
    transports: [
        new winston.transports.File({ filename: "error.log" })
    ]
});

MiddlewarePipeline.addMiddleware((req, res, next) => {
    try {
        next();
    } catch (error) {
        logger.error({
            message: error.message,
            stack: error.stack,
            method: req.method,
            url: req.url,
            timestamp: new Date().toISOString()
        });
        
        res.sendJson({ error: "Internal Server Error" }, 500);
    }
});

Error Monitoring Integration

Integrate with error monitoring services for production environments:
import * as Sentry from "@sentry/node";

Sentry.init({ dsn: process.env.SENTRY_DSN });

MiddlewarePipeline.addMiddleware((req, res, next) => {
    try {
        next();
    } catch (error) {
        // Send to Sentry
        Sentry.captureException(error, {
            extra: {
                method: req.method,
                url: req.url,
                headers: req.headers
            }
        });
        
        console.error(error);
        res.sendJson({ error: "Internal Server Error" }, 500);
    }
});

Use Cases

  • Production Safety: Prevent server crashes from uncaught exceptions
  • Client Experience: Provide consistent error responses to API consumers
  • Debugging: Centralized error logging for easier troubleshooting
  • Security: Hide internal implementation details from clients
  • Monitoring: Single point to integrate with error tracking services