/** * DashCaddy Error Handler Middleware * Centralizes error handling logic to eliminate duplicate catch blocks * * Logging: this middleware uses the unified logError from src/utils/logging.js * (same one src/app.js uses), so all errors go to one log file. The legacy * ./error-logger.js and its ./error.log file have been retired. */ const path = require('path'); const { AppError } = require('./errors'); const { LIMITS } = require('./constants'); const { logError: unifiedLogError, safeErrorMessage } = require('./src/utils/logging'); const { errorResponse } = require('./src/utils/responses'); const ERROR_LOG_FILE = path.join(__dirname, 'error.log'); const MAX_ERROR_LOG_SIZE = LIMITS.ERROR_LOG_SIZE; /** * Global error handling middleware * MUST be registered after all routes in server.js */ function errorMiddleware(err, req, res, next) { // Log all errors with request context (unified, same file the rest of the app uses) unifiedLogError( ERROR_LOG_FILE, MAX_ERROR_LOG_SIZE, req.path, err, { method: req.method, ip: req.ip, userId: req.user?.id, body: req.body } ).catch(e => console.error('Failed to write to error log:', e.message)); // Determine if this is an operational error (AppError) or programming error const isOperational = err.isOperational || err instanceof AppError; // Status code const statusCode = err.statusCode || 500; // Error code (DC-XXX format) const code = err.code || `DC-${statusCode}`; // Build extras for response const extras = { code }; // Add optional fields if present if (err.requiresTotp) extras.requiresTotp = true; if (err.retryAfter) extras.retryAfter = err.retryAfter; if (err.field) extras.field = err.field; if (err.resource) extras.resource = err.resource; if (err.details && Object.keys(err.details).length > 0) extras.details = err.details; // Development mode: include stack trace if (process.env.NODE_ENV === 'development') { extras.stack = err.stack; } // Send response errorResponse(res, statusCode, isOperational ? safeErrorMessage(err) : 'Internal server error', extras); // For non-operational errors, log as fatal if (!isOperational) { console.error('FATAL: Non-operational error detected', { error: err.message, stack: err.stack, path: req.path }); } } /** * 404 handler for routes not found * Register this before the global error handler */ function notFoundHandler(req, res, next) { const { NotFoundError } = require('./errors'); next(new NotFoundError(`Route ${req.method} ${req.path}`)); } module.exports = { errorMiddleware, notFoundHandler };