Quiz: Advanced JS Error Mastery
Are your exceptions truly exceptional?
Think you know JavaScript errors inside and out?
- Test your error handling expertise! 💥
- No login or signup required. ✨
- Multiple choice. 🤖 … These ain’t your typical try-catch questions!
What does JSON.stringify(error) return?
const error = new Error('Oops');console.log(JSON.stringify(error));Think about enumerable properties on Error objects.
Error objects have non-enumerable properties (message, name, stack), so JSON.stringify() returns {}. This is a common gotcha when sending errors in API responses. Use JSON.stringify(error, Object.getOwnPropertyNames(error)) or create a plain object instead.
What’s the difference between these two?
const err = new Error('Test');console.log(err);console.log(JSON.stringify(err));Consider how console.log handles objects vs JSON serialization.
console.log(err) shows the error with its message and stack trace because the console has special handling for Error objects. JSON.stringify(err) returns '{}' because Error properties aren’t enumerable. This difference trips up many developers debugging APIs.
What are the results of these checks?
class CustomError extends Error {}const err = new CustomError('test');
console.log(err instanceof CustomError);console.log(err instanceof Error);console.log(err instanceof Object);Remember the prototype chain in JavaScript inheritance.
All three return true. CustomError extends Error, which extends Object. The instanceof operator checks the entire prototype chain, so a CustomError instance is also an instance of Error and Object.
Assume iframeError was created in a same-origin iframe and passed to its parent window.
console.log(iframeError instanceof Error);Different contexts have different Error constructors.
Different realms have different Error constructors, so this check can return false. Object.prototype.toString.call(obj) can recognize ordinary cross-realm errors, but Symbol.toStringTag can spoof its result; it is not an authenticity check.
What happens when you throw a string?
try { throw "Oops!";} catch (e) { console.log(e instanceof Error); console.log(typeof e);}JavaScript allows throwing any value, not just Error objects.
JavaScript allows throwing any value. Here, e instanceof Error is false and typeof e is "string". This can break error handling code that assumes all caught exceptions are Error objects. Always throw Error instances for better debugging.
What’s the value of err.name?
class CustomError extends Error { constructor(message) { super(message); this.name = this.constructor.name; }}const err = new CustomError('test');console.log(err.name);Look at what this.constructor.name evaluates to.
err.name is "CustomError" because this.constructor.name returns the class name. Setting this.name = this.constructor.name is a common pattern to ensure custom error classes display the correct name in stack traces and error messages.
What’s the output without setting name?
class MyError extends Error { // No constructor or name setting}const err = new MyError('test');console.log(err.name);What does Error’s default name property contain?
Without explicitly setting this.name, the error inherits the default name property from the Error class, which is "Error". This is why custom error classes should always set this.name = this.constructor.name in their constructor.
What does wrapper.cause.message return?
const original = new Error('Original error');const wrapper = new Error('Wrapper', { cause: original });console.log(wrapper.cause.message);Error.cause is a modern JavaScript feature for error chaining.
Error.cause (ES2022) allows chaining errors to preserve the original error context. wrapper.cause references the original error, so wrapper.cause.message returns "Original error". This is useful for wrapping lower-level errors with higher-level context.
Assume V8/Node.js, where Error.captureStackTrace is available.
What does Error.captureStackTrace do?
function createError(msg) { const err = new Error(msg); Error.captureStackTrace(err, createError); return err;}const error = createError('test');This is a V8-specific feature for cleaner stack traces.
Error.captureStackTrace (V8/Node.js) removes the specified function (createError) from the stack trace, making error factory functions invisible to end users. This creates cleaner stack traces that point to where the factory was called, not the factory itself.
What’s the error message?
function validate(value) { if (!value) { throw new Error( `Value ${value} is invalid` ); }}try { validate(undefined);} catch (e) { console.log(e.message);}How does template literal interpolation handle undefined?
Template literals convert undefined to the string "undefined" during interpolation. The error message becomes "Value undefined is invalid". For cleaner messages, consider using value ?? 'null' or similar checks before interpolation.
What gets sent to the client?
// Express.js routeapp.get('/api/data', (req, res) => { const error = new Error('Database failed'); res.json({ error });});Remember how Error objects are serialized by JSON.stringify.
res.json() uses JSON.stringify() internally, so the Error object becomes {}. The client receives {"error":{}}. To fix this, use res.json({ error: error.message }) or res.json({ error: { message: error.message, name: error.name } }).
What can Promise.reject() accept?
Promise.reject('string').catch(e => console.log(typeof e));Promise.reject({code: 404}).catch(e => console.log(e.code));Promise.reject(42).catch(e => console.log(e));Promise rejections work similar to throw statements.
Like throw, Promise.reject() accepts any value - strings, objects, numbers, etc. This prints "string", 404, and 42. Always check the type of caught values in promise chains, especially when dealing with third-party code that might reject with non-Error values.
How reliable are error.code and error.errno?
const fs = require('fs');fs.readFile('missing.txt', (err, data) => { if (err) { console.log(err.code); // 'ENOENT' console.log(err.errno); // -2 }});Consider different JavaScript environments and error types.
Properties like code and errno are environment-specific (Node.js in this case) and not part of the standard Error object. Browser errors won’t have these properties. Always check for their existence: if (err.code === 'ENOENT') rather than assuming they exist.
What do these checks return?
const fakeError = { name: 'Error', message: 'Fake error', stack: 'fake stack'};
console.log(fakeError instanceof Error);console.log(Object.prototype.toString.call( fakeError) === '[object Error]');One check follows the prototype chain; the other reports an object tag that can be influenced by Symbol.toStringTag.
Both comparisons are false for this exact object. Its prototype is not Error.prototype, and its default tag is [object Object]. However, adding [Symbol.toStringTag]: "Error" would make the second comparison true. Neither a matching tag nor these fields proves that an object is an authentic Error.
Master the Art of Error Handling
From serialization gotchas to cross-context instanceof failures, these advanced concepts separate junior developers from seasoned damaged professionals.
Ready for more challenges? Check out our complete quiz collection for additional brain teasers on JavaScript, algorithms, and more!
