Glossary / Custom errors
Custom errors
Custom error classes represent domain-specific or application-specific failures that callers can classify and handle. A useful type communicates a stable category—such as ValidationError, NotFoundError, or ConflictError—and may carry safe machine-readable metadata. The goal is to enable correct recovery, not to create a subclass for every possible message.
A robust error type
class ValidationError extends Error {
constructor(message, options = {}) {
super(message, options);
this.name = "ValidationError";
this.code = "INVALID_INPUT";
this.field = options.field;
}
}
In supported runtimes, Error’s cause option preserves lower-level context. Keep message for people and stable codes/types for program logic; message text may be edited, localized, or include variable data. If targeting older engines or transpilation, verify subclass behavior and stack/name handling.
At API boundaries, map internal errors to safe status codes and public messages. Do not expose secrets, query text, or stack traces. Avoid an overly granular taxonomy that callers cannot use meaningfully. Some failures are better represented as explicit result values (for example, expected validation outcomes) than thrown exceptions; choose based on control-flow and recovery semantics.
Interview questions
- What should callers branch on? Stable error class or code, not message text.
- How preserve an underlying error? Use
causewhen wrapping it with context. - Should every domain failure be an exception? No; expected alternative outcomes may be clearer as result values.
- Why map errors at an API boundary? To preserve internal diagnostics while exposing safe, stable external contracts.