Skip to content
Chapter 8Lesson 3

Quiz - Errors as a first-class concern

Quiz progress

0 / 0

A signUp(email, password) Server Action can fail in three ways: the email is already taken, the password is shorter than the minimum, and the Postgres pool is exhausted. Which channels should each failure ride?

Duplicate-email and short-password return a Result<T, E>; pool exhaustion throws.

All three return a Result<T, E> with a tagged-union E — that’s the whole point of Result.

All three throw — the action’s outer catch translates each into a user-visible message.

Which of these try/catch shapes is broken? Select all that apply.

try {
return fetchUser(id);
} catch (err) {
return null;
}
try {
void logEvent(e);
} catch (err) {
return null;
}
try {
return await fetchUser(id);
} catch (err) {
return null;
}
try {
await logEvent(e);
} catch {
/* swallow */
}

A catch in a Server Component receives an error thrown by Next.js middleware running on the edge runtime. Which narrow is the right reach?

Error.isError(err) — middleware and Server Components run in different realms, so instanceof Error returns false on a real Error from the other side.

err instanceof Error — the standard narrow works for any thrown Error, regardless of where it came from.

typeof err === 'object' && err !== null && 'message' in err — duck-typing dodges the realm issue.

Which of these BillingError class shapes follow the 2026 senior pattern? Select all that apply.

class BillingError extends Error {
readonly name = 'BillingError' as const;
readonly code: 'card_declined' | 'insufficient_funds';
constructor(code: 'card_declined' | 'insufficient_funds', message: string, options?: { cause?: unknown }) {
super(message, options);
this.code = code;
}
}
abstract class AppError extends Error {}
class BillingError extends AppError {
constructor(code: string, message: string) {
super(`BillingError: ${message}`);
this.name = 'BillingError';
(this as any).code = code;
}
}
class BillingError extends Error {
readonly name = 'BillingError' as const;
readonly code: 'card_declined' | 'insufficient_funds';
constructor(code: 'card_declined' | 'insufficient_funds', message: string) {
super(message);
this.code = code;
}
}

A function returns Result<Invoice[], ParseError>. What’s the structural payoff over throwing on every parse failure?

The compiler refuses to read value until the caller has checked ok, and adding a new variant to ParseError turns every consumer’s switch into a compile error until they handle it.

Result is faster — throwing builds a stack trace, returning a tagged object doesn’t.

Result propagates up the call stack the same way a throw would, but without the unknown-typed catch parameter.

Reorder this catch ladder into the canonical 2026 shape.

try {
await processCharge(invoiceId);
} catch (e) {
// A — throw ensureError(e);
// B — if (e instanceof BillingError) { switch (e.code) { ... } }
// C — if (e instanceof Error) throw e;
// D — if (e instanceof Error && e.name === 'AbortError') return;
}
B, D, C, A
C, B, D, A
A, B, D, C

You catch a StripeCardError at the Stripe seam and want to rethrow it as a BillingError so the operator log still has the original Stripe response. What’s the right shape?

throw new BillingError('card_declined', 'Card declined by issuer', { cause: stripeErr });
throw new BillingError('card_declined', `Card declined: ${stripeErr.message} (${stripeErr.code})`);
stripeErr.name = 'BillingError';
throw stripeErr;

A catch wraps a vendor SDK call and console.error(err)s, then continues with the original happy-path return. What’s the senior critique?

The catch neither converts the channel to Result.err nor lets the boundary handle the failure — the caller sees success even though the call failed. Either recover and return err({ ... }), or remove the catch and let the throw bubble.

console.error is the wrong logger — swap it for the project’s structured logger and the catch is fine.

The catch parameter should be typed Error, not unknown — narrow with instanceof Error and the shape becomes correct.

Quiz complete

Score by topic