JavaScript Runtime Semantics
Errors, Exceptions & Stack Traces
JavaScript can throw any value, but production code should throw Error objects or subclasses so stack traces, names, causes, and handling stay useful.
- Thrown values interrupt normal control flow
- Throw Error objects, not strings
- Use
causeto preserve lower-level failures - Async errors flow through Promises
- Domain errors should be distinguishable
class ValidationError extends Error {
constructor(message, details) {
super(message)
this.name = "ValidationError"
this.details = details
}
}
try {
saveUser(input)
} catch (err) {
if (err instanceof ValidationError) {
showFieldErrors(err.details)
} else {
throw err
}
}| Pattern | Use for | Watch out |
|---|---|---|
| throw Error | Exceptional failure | Must be caught at boundary |
| Result object | Expected recoverable failure | Callers must check |
| Error subclass | Domain-specific handling | Keep inheritance simple |
| cause | Wrap lower-level error | Preserve original context |