Advanced - ds-express-errors


Global Exception Handlers

Node.js apps can crash due to uncaughtException or unhandledRejection.
initGlobalHandlers catches these process-level errors, logs them, and allows for a graceful shutdown (closing DB connections, server sockets, etc.).

Basic Usage

Initialize this at the entry point of your application (e.g., `index.js`).

javascript
import { initGlobalHandlers } from 'ds-express-errors';

// Will log the error and process.exit(1)
initGlobalHandlers();

Graceful Shutdown & Global Handlers

Read more about graceful shutdown

DS Express Errors provides a robust way to handle application crashes and termination signals (SIGINT, SIGTERM). It ensures your server stops accepting new connections and finishes active requests before exiting.

Work from v1.5.0+:

  • initGlobalHandlers now supports full graceful shutdown:
  • Asynchronous onCrash(error, signal) is automatically awaited with a default 10-second timeout. (or you can set maxTimeout to change it) The library calls process.exit(1) after it completes, so you no longer need to exit manually.
  • New onShutdown(signal) handler for normal shutdowns (SIGTERM, SIGINT, SIGQUIT ).
  • Support for closeServer(signal) to safely close an HTTP server, including handling AbortSignal.
  • Built-in safeShutdown prevents repeated shutdown calls and logs forced exits (Forced exit from graceful shutdown).
  • Timeout and AbortSignal are applied to all long-running async operations to avoid blocking process exit.

javascript
import { initGlobalHandlers, gracefulHttpClose } from 'ds-express-errors';

const server = app.listen(3000);

initGlobalHandlers({
  closeServer: gracefulHttpClose(server), // Gracefully close server

  onShutdown: async (signal) => {
    console.log('Cleaning up...');
    await mongoose.disconnect(); // Close DB connections
  },

  onCrash: async (err, signal) => {
    await sendAlertToAdmin(err); // Notify dev team about crash
  }
});

Custom Response Formatting

Read more about configuration

By default, the library sends responses in a standard format (`status`, `message`, `url`). You can completely override this structure using the setConfig method.

json
{
  "status": "error", // or 'fail'
  "method": "GET", //dev only
  "url": "/api/resource", //dev only
  "message": "Error description",
  "stack": ... //dev only
}

Operational vs. Programmer Errors

The library distinguishes between two types of errors using the isOperational flag:

  1. Operational Errors (isOperational: true): Expected runtime problems (e.g., "User not found", "Validation failed"). The application can continue running. All Presets result in operational errors.
  2. Programmer Errors (isOperational: false): Bugs in the code (e.g., TypeError, SyntaxError, trying to access undefined). The best practice is to crash and restart the app to avoid inconsistent state.

The global handler logs Operational: false errors with high severity.

Creating Custom Error Classes

You can extend AppError to create domain-specific errors for your application.

javascript
import { AppError } from 'ds-express-errors';

class SubscriptionExpiredError extends AppError {
    constructor(message = 'Your subscription has expired') {
        // Pass message and 402 (Payment Required) status
        super(message, 402, true); 
    }
}

// Usage in controller
app.post('/premium-content', (req, res, next) => {
    if (user.subscriptionStatus === 'expired') {
        throw new SubscriptionExpiredError();
    }
});


Have some ideas? Find something missing? or Bug?

Share your suggestions with us!