In this lesson, you will learn how to safely expose error details during local development while suppressing sensitive technical telemetry in production to prevent information leakage and performance bottlenecks.
The Problem of Verbosity
When developing locally, you want a "noisy" application. Seeing the full stack trace, variable states, and internal module paths is essential for rapid debugging. However, when you move that same code to production, those details become a liability. Attackers can use stack traces to map your internal architecture, and excessive logging of full error objects can create significant I/O overhead, potentially delaying response times or bloating your logs.
Designing an Error Handler
To manage this, we implement an environment-aware error handler that serves as a gatekeeper. Instead of throwing raw errors directly to the client, we categorize them based on the NODE_ENV variable.
function handleError(err, res) {
const isDev = process.env.NODE_ENV === 'development';
if (isDev) {
// Development: Full transparency for the developer
res.status(500).json({
message: err.message,
stack: err.stack,
details: err.data
});
} else {
// Production: Opaque, secure, and performant
// Log the full error internally, but hide it from the user
console.error(`Internal Error: ${err.message}`);
res.status(500).json({
message: 'An internal error occurred. Please try again later.',
correlationId: res.get('X-Correlation-ID') // Useful for support tracking
});
}
}
Why this is Advanced
At this level, you must treat errors as two distinct data streams: telemetry and responses. In production, your error handler should trigger a "soft" failure or generic response to the user, while simultaneously ensuring that the rich diagnostic data (which you would have printed in development) is sent to a centralized logging service or a crash-reporting tool. This separation ensures your production system remains a "black box" to the outside world while maintaining the high observability required for enterprise-grade resilience.
Key Takeaway: Never leak raw stack traces or internal state to end-users in production; instead, decouple the human-readable response from your high-fidelity internal diagnostics.