Skip to main content
This document is a focused technical audit of error handling and resilience for an API/Node.js (Express) application. It condenses a broader quality review into concrete findings, prioritized remediation, and precise, drop-in code fixes you can apply quickly to reduce risk and improve uptime.
A presentation slide titled "Error Handling & Resilience Audit" with a large "Demo" label on a dark curved background. A small "© Copyright KodeKloud" appears in the bottom-left corner.
Purpose: identify gaps in error handling consistency, categorization, async handling, recovery patterns, and error information exposure — then provide targeted code snippets and configuration changes that are minimal to integrate. Example prompt used to drive the audit (trimmed for clarity):
Evaluation checklist used during the audit:
  • ERROR HANDLING CONSISTENCY
    • Centralized error handler?
    • Uniform response formats?
    • Custom error classes vs generic errors?
  • ERROR CATEGORIES
    • Validation (400), Authentication (401), Authorization (403), Not found (404), Server (500), Rate limit (429), Conflict (409)
  • ASYNC ERROR HANDLING
    • Unhandled promise rejections
    • Async middleware wrapper usage
    • Callback & EventEmitter error handling
  • ERROR RECOVERY
    • Graceful degradation
    • Retry mechanisms
    • Circuit breakers
    • Fallback strategies
  • ERROR INFORMATION
    • Dev vs Prod error detail
    • Stack trace exposure
    • Error logging completeness
    • User-friendly error messages

Executive summary

Status: ❌ CRITICAL DEFICIENCIES IDENTIFIED
Overall Score: 3.5 / 10
The Express Login Demo exposes several critical error-handling and resilience gaps. Primary risks include lack of centralized error handling, leakage of sensitive information in logs/responses, missing global handlers for unhandled rejections/uncaught exceptions, and no recovery patterns (retries/circuit breakers/fallbacks). Most critical security-related fixes are small and can be implemented in ~1 week. Reaching full resilience maturity (observability, circuit breakers, graceful degradation) is estimated at 2–3 months. Critical findings overview:

1. ERROR HANDLING CONSISTENCY

Finding
  • No centralized error middleware is plugged in after routes.
  • Route handlers return heterogeneous response shapes and sometimes directly call console.error.
  • No standard error object or machine-readable error payload.
Remediation — minimal, drop-in utilities
  • Standardized error response object:
  • Central HTTP error class:
  • Centralized Express error-handling middleware (register after all routes):
Integration tip: Replace ad-hoc responses with next(new HTTPError('message', 400)). Ensure app.use(errorHandler) is the final middleware.

2. ERROR CATEGORIES

Finding
  • Routes occasionally use 400/401/500, but 403, 404, 409, and 429 are inconsistent or missing.
  • Lack of helpers leads to human error and inconsistent client behavior.
Remediation — helper factory for consistent HTTP errors
Usage example:

3. ASYNC ERROR HANDLING

Findings
  • No global process.on('unhandledRejection') or process.on('uncaughtException') handlers.
  • Route handlers use manual try/catch or nothing; no async wrapper in place.
  • Potential for unhandled promise rejections to crash the process unpredictably.
Remediation
  • Add global process handlers (put these near server startup, before app.listen()):
  • Async wrapper middleware (very small, drop-in):
Usage:
This pattern ensures thrown errors are forwarded to the centralized errorHandler.

4. ERROR RECOVERY

Findings
  • No retry logic for transient failures (database, network).
  • No circuit breaker to prevent rapid cascading failures to dependencies.
  • No fallback or graceful degradation for non-critical features.
Remediation — small, practical utilities
  • Simple retry helper with exponential backoff:
Example usage with Mongoose:
  • Lightweight circuit breaker to protect fragile external calls:
Apply CircuitBreaker.fire(() => remoteCall()) for DB/third-party services. For production-grade resilience, consider libraries like opossum which offer metrics and event hooks.

5. ERROR INFORMATION (LOGGING & EXPOSURE)

Findings
  • Console logging of full error objects and DB details leaks secrets.
  • No structured logging; logs are inconsistent and hard to search.
  • Stack traces are returned to clients in production in some cases.
Remediation — structured logger + sanitization
  • Replace console.log/console.error with a structured logger like winston:
  • Sanitize logs and responses: ensure sanitizeError strips fields like password, connectionString, ssn before logging or returning to clients.
  • Environment-specific responses: only include stack traces in development. In production, return minimal messages and include a reference ID to correlate logs:
Record the reference in structured logs for post-mortem.

PRIORITY REMEDIATION PLAN

Immediate (Week 1) — Critical
  1. Add and register centralized errorHandler middleware; replace ad-hoc responses.
  2. Add global unhandledRejection / uncaughtException handlers and ensure server.close() is used for graceful shutdown.
  3. Replace console with structured logger and add basic sanitization rules.
Short-term (Month 1) 4. Add asyncWrapper for routes and refactor handlers to use it. 5. Adopt standardized HTTP error helpers and ensure all routes use them. 6. Use retry helper for transient DB/network operations. Medium-term (Month 2–3) 7. Integrate circuit breakers around external dependencies. 8. Implement graceful degradation and fallback strategies for non-critical features. 9. Add rate limiting (return 429) and monitoring/alerts tied to error thresholds and circuit breaker events.
Prioritize fixes that remove secret leakage from logs and add global rejection handlers — these reduce attack surface and prevent abrupt crashes.

SECURITY IMPACT & READINESS

Production Readiness: NOT READY After applying prioritized fixes:
  • Error information disclosure: LOW RISK
  • Application stability: MEDIUM → HIGH (once retries/circuit breakers are in place)
  • Debugging & observability: SIGNIFICANTLY IMPROVED (with structured logging and reference IDs)
Estimated time:
  • Critical fixes: 2–3 weeks (depending on testing and rollout strategy)
  • Full resilience (monitoring, circuit breakers, graceful degradation): 2–3 months

Notes on verification

  • If repository snapshot lacks specific files or code locations, mark the finding as “Unable to verify” and list the exact evidence that would validate the finding (e.g., “routes/auth.js contains console.error(err) with full err object logged” or “no process.on('unhandledRejection') handler present in server startup file”).
  • Prefer minimal, drop-in snippets to make integration easier.
  • Keep a checklist of files changed and tests added to verify behavior (unit tests for asyncWrapper, integration tests for retry and circuitBreaker).

The full technical audit (structured findings, importance scores, and all suggested code snippets) was written to audits/ERROR_HANDLING_COMPREHENSIVE_REVIEW.md per the audit prompt. Implementing the above will materially improve resilience, security, and production readiness.

Watch Video