Skip to content

typescript.express.missing_error_middleware

Stability Medium

Detects Express apps without error handling middleware.

Without error middleware:

  • Unhandled errors crash — Process exits on uncaught exceptions
  • Information leakage — Stack traces shown to users
  • Inconsistent responses — Different error formats
  • Silent failures — Errors not logged
// ❌ Before
const app = express();
app.get('/users/:id', async (req, res) => {
const user = await getUser(req.params.id); // Throws on error
res.json(user);
});
app.listen(3000);

If getUser throws, the request hangs or crashes.

// ✅ After
const app = express();
app.get('/users/:id', async (req, res, next) => {
try {
const user = await getUser(req.params.id);
res.json(user);
} catch (error) {
next(error);
}
});
// Error handling middleware (must be last)
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error('Error:', err);
res.status(500).json({ error: 'Internal server error' });
});
app.listen(3000);
  • Express app without error middleware
  • Missing next(error) in async handlers
  • Express app without try/catch in handlers

Unfault adds error handling middleware and suggests wrapping async handlers.

// Async wrapper helper
const asyncHandler = (fn: RequestHandler) =>
(req: Request, res: Response, next: NextFunction) =>
Promise.resolve(fn(req, res, next)).catch(next);
app.get('/users/:id', asyncHandler(async (req, res) => {
const user = await getUser(req.params.id);
res.json(user);
}));
// Custom error class
class AppError extends Error {
constructor(public statusCode: number, message: string) {
super(message);
}
}
// Error middleware with custom errors
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
if (err instanceof AppError) {
return res.status(err.statusCode).json({ error: err.message });
}
console.error('Unhandled error:', err);
res.status(500).json({ error: 'Internal server error' });
});