JS Error Object
In this page:
error.name
error.message
error.stack
The name, message, and stack Properties
Every Error object carries three key properties: .name identifies the error type (like TypeError), .message holds the human-readable description you (or the engine) provided, and .stack contains a trace of the function calls that led to where the error was created, invaluable for tracking down exactly where something went wrong.
Example: The name, message, and stack Properties
// Try running this block; jump to `catch` if it throws
// Try running this block; jump to `catch` if it throws
try {
null.name;
// Catch any error, bound to `e`
// Catch any error, bound to `e`
} catch (e) {
// Print `e.name, e.message` to the console
// Print `e.name, e.message` to the console
console.log(e.name, e.message);
// Print `e.stack` to the console
// Print `e.stack` to the console
console.log(e.stack);
}
Throwing Non-Error Values
JavaScript's throw statement accepts any value at all -- a string, a number, a plain object -- not just an Error instance, but doing so loses the standard name/message/stack structure, making the thrown value harder to work with consistently in a catch block that expects a real Error.
Example: Throwing Non-Error Values
try {
throw "just a string"; // not an Error instance
} catch (e) {
console.log(typeof e, e); // no .name/.message/.stack structure
}
Adding Custom Properties to an Error
Beyond the standard three properties, you can attach additional custom properties directly to an Error instance after creating it -- like a specific error code, an HTTP status, or contextual data relevant to what failed -- extending the base Error object without needing a full custom subclass.
Example: Adding Custom Properties to an Error
// Declare the constant `err` as a new `Error` instance
// Declare the constant `err` as a new `Error` instance
const err = new Error("Something failed");
// Assign "E_CUSTOM" to `err.code`
// Assign "E_CUSTOM" to `err.code`
err.code = "E_CUSTOM";
// Assign `500` to `err.statusCode`
// Assign `500` to `err.statusCode`
err.statusCode = 500;
// Print `err.code, err.statusCode, err.message` to the console
// Print `err.code, err.statusCode, err.message` to the console
console.log(err.code, err.statusCode, err.message);
The cause Property
A more recent addition, the cause option (passed as the second argument to Error's constructor: new Error(message, { cause: originalError })) lets you chain errors together, preserving the original underlying error while wrapping it in a more specific, higher-level one.
Example: The cause Property
// Try running this block; jump to `catch` if it throws
// Try running this block; jump to `catch` if it throws
try {
// Try running this block; jump to `catch` if it throws
// Try running this block; jump to `catch` if it throws
try {
// Throw a new `Error` with message "Original failure"
// Throw a new `Error` with message "Original failure"
throw new Error("Original failure");
// Catch any error, bound to `original`
// Catch any error, bound to `original`
} catch (original) {
// Throw a new `Error` with message `"Higher-level failure", { cause: original }`
// Throw a new `Error` with message `"Higher-level failure", { cause: original }`
throw new Error("Higher-level failure", { cause: original });
}
// Catch any error, bound to `e`
// Catch any error, bound to `e`
} catch (e) {
// Print `e.message, "caused by:", e.cause.message` to the console
// Print `e.message, "caused by:", e.cause.message` to the console
console.log(e.message, "caused by:", e.cause.message);
}
Serializing Errors for Logging
An Error object does not serialize usefully with JSON.stringify() by default -- its enumerable-property scan misses name, message, and stack, since they are defined as non-enumerable on the base Error prototype -- so sending or logging error details in JSON form requires manually extracting the properties you need first.
Example: Serializing Errors for Logging
const err = new Error("Failed");
console.log(JSON.stringify(err)); // "{}" - name/message/stack are non-enumerable
console.log(JSON.stringify({ name: err.name, message: err.message }));
- Assuming every thrown value is actually an Error object -- JavaScript allows throwing any value at all (a string, a number), which lacks the standard name/message/stack properties an Error provides.
- Overwriting or ignoring the stack property when logging an error, losing the exact call-path information that would help pinpoint where the error actually originated.
- Constructing a new Error() without a descriptive message, producing an error that is technically informative to the code but unhelpfully vague to whoever reads the log later.
- new Error(message) creates an Error object with .name ("Error" by default), .message (your description), and .stack (a call trace).
- Built-in error subtypes (TypeError, RangeError, and others) all inherit from the base Error object, sharing its core properties.
- JavaScript technically allows throwing any value, not just an Error object -- but throwing a real Error (or a subclass) is strongly recommended for consistency.
The Error object and its core properties have been supported in every browser since JavaScript's earliest versions.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: