Node.js Error Handling: From try/catch to Production Error Monitoring

Node.js Error Handling: From try/catch to Production Error Monitoring
0 views

Most Node.js error handling is an afterthought — catch blocks that swallow errors and generic 500 responses. Production-quality error handling requires custom error classes, structured logging, global handlers, and integration with error tracking services like Sentry.

⚡ TL;DR: Custom AppError with code/statusCode/isOperational. asyncHandler wrapper for async routes. 4-param Express error middleware at end. unhandledRejection handler that exits. Structured JSON logging. Sentry for non-operational errors.

Custom error hierarchy — Node.js error handling

class AppError extends Error {
  constructor(message, code, statusCode=500, isOperational=true) {
    super(message);
    this.code = code;           // 'USER_NOT_FOUND'
    this.statusCode = statusCode;
    this.isOperational = isOperational;
    Error.captureStackTrace(this, this.constructor);
  }
}

class NotFoundError extends AppError {
  constructor(resource, id) {
    super(`${resource} ${id} not found`, 'NOT_FOUND', 404);
  }
}

class ValidationError extends AppError {
  constructor(msg, fields={}) {
    super(msg, 'VALIDATION_FAILED', 422);
    this.fields = fields;
  }
}

asyncHandler — no try/catch in routes

const asyncHandler = fn => (req,res,next) =>
  Promise.resolve(fn(req,res,next)).catch(next);

app.get('/users/:id', asyncHandler(async (req,res) => {
  const user = await UserService.findById(req.params.id);
  if(!user) throw new NotFoundError('User', req.params.id);
  res.json(user);
}));

Express error middleware

// MUST have 4 params — tells Express it's error handler
app.use((err, req, res, next) => {
  logger.error('Request error', {
    err: {code:err.code, message:err.message},
    req: {method:req.method, url:req.url, userId:req.user?.id}
  });
  if(!err.isOperational) Sentry.captureException(err);
  res.status(err.statusCode||500).json({
    error: {
      code: err.code||'INTERNAL_ERROR',
      message: err.isOperational ? err.message : 'Something went wrong'
    }
  });
});

Global handlers

process.on('unhandledRejection',(reason)=>{
  logger.error('Unhandled rejection',{reason});
  Sentry.captureException(reason);
  setTimeout(()=>process.exit(1),1000);
});

process.on('uncaughtException',(error)=>{
  logger.error('Uncaught exception',{error});
  Sentry.captureException(error);
  setTimeout(()=>process.exit(1),1000);
});

process.on('SIGTERM',async()=>{
  server.close(async()=>{ await db.end(); process.exit(0); });
  setTimeout(()=>process.exit(1),30000);
});
  • ✅ Custom error classes with code, statusCode, isOperational
  • ✅ asyncHandler — single wrapper instead of try/catch in every route
  • ✅ 4-param error middleware at end of Express app
  • ✅ Global unhandledRejection + uncaughtException handlers
  • ✅ Graceful shutdown on SIGTERM
  • ❌ Never swallow errors in empty catch blocks
  • ❌ Never expose stack traces in production responses

Error handling pairs with API security — never expose internals. External reference: Joyent Node.js error guide.

Recommended Reading

→ Designing Data-Intensive Applications — The bible of distributed systems and production engineering at scale.

→ The Pragmatic Programmer — Timeless engineering wisdom every senior developer needs.

Affiliate links. We earn a small commission at no extra cost to you.

Free Weekly Newsletter

🚀 Join 2,000+ Senior Developers

Get expert-level JavaScript, Python, AWS, system design and AI secrets every week. Zero fluff, pure signal.

✓ No spam✓ Unsubscribe anytime✓ Expert-level only

Related: Node.js Error Handling: From try/catch to Production Error Monitoring · Express.js Best Practices: Build Production-Ready APIs With Node.js · Node.js Security Best Practices: Protect Your API From the Most Common Attacks

Related: Lambda Timeouts, Retries, and DLQs: Idempotent Failure Handling · Node.js Async Hooks: The Tracing API That Powers Every APM Tool · Python Context Managers: Master the with Statement for Clean Resource Handling

Deep-dive PDF

Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.

Already subscribed? or open the subscribe page.


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a comment

No account needed. Name and email are optional.