Skip to main content
JavaScript & the browser·Module C7 · Lesson 7
TaskWrite outer(inner) that wraps an awaited Promise with try/catch and re-throws a new Error('outer failed', { cause: original }). Call outer(Promise.reject(new TypeError('inner boom'))) inside try/catch and log err.message, err.cause.name, err.cause.message.

Error chaining with the cause option

125 XP8 min
Theory

Wrapping low-level errors

When a low-level error happens deep in the stack, you usually want to add context before re-throwing — but you don't want to lose the original error. The { cause } option on Error does both:

async function loadProfile(userId) {
  try {
    return await db.findUser(userId);
  } catch (err) {
    throw new Error(\`failed to load profile for ${userId}\`, { cause: err });
  }
}

The caller catches the high-level error AND can drill into err.cause to inspect the original.

try {
  await loadProfile("u_123");
} catch (err) {
  console.error(err.message);        // "failed to load profile for u_123"
  console.error(err.cause?.message); // the underlying db error
}

Why not just re-throw?

Re-throwing keeps the message but loses the "where in the high-level flow did this happen" context. Wrapping adds business semantics; cause preserves the technical detail. Both layers stay available.

Stack vs cause

.stack shows where it was thrown. .cause shows what triggered it. Together they're invaluable in production logs.

🔒

Sign up to start coding

Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial — card required, cancel anytime.

Sign up — free trial →

First 15 lessons in each track are free. No card needed for those.

PreviousNext lesson →

Get one Python or web tip a day — by email

Short, hand-written, no spam. Unsubscribe in one click.