Using predefined error constants like const VALIDATION_ERROR = new Error('Invalid input');
may seem convenient, but it introduces misleading stack traces, which can complicate debugging and error tracking.
The Issue: Misleading Stack Traces
When you create an error object, its stack trace is captured at the point of instantiation. If you reuse a predefined error, its stack trace points to where it was defined, not where it was thrown.
const VALIDATION_ERROR = new Error('Invalid input');
function validateInput(input) {
if (typeof input !== 'string') {
throw VALIDATION_ERROR; // Stack trace points to definition, not here
}
}
This makes it harder to locate the actual cause of the error.
Better Approach: Create Errors Dynamically
To ensure accurate stack traces, instantiate the error when throwing it:
function validateInput(input) {
if (typeof input !== 'string') {
throw new Error('Invalid input'); // Stack trace points here
}
}
For reusable error messages, use an error factory:
function createValidationError(message) {
return new Error(message);
}
Why It Matters
- Accurate Debugging: Stack traces point to the actual problem.
- Better Tool Integration: Tools like Bugsnag and Sentry rely on correct stack traces.
- Clarity: Makes finding and fixing issues faster and easier.
Avoid predefined errors to simplify debugging and improve maintainability.