AI InterviewSearch…Search problems, topics, or pages…Ctrl KGet started
Skip to content

07 Errors and error handling / Checkpoint

Checkpoint — Errors

24 min · +25 XP · 3 exercises · 12 questions

Exercises0/3
Quiz · 70% to clear12 q

This checkpoint covers the mechanics of throw/try/catch/finally (including what finally overrides and when the stack is captured), the built-in error types and what triggers each, designing custom errors with name, code, fields and cause, the boundary strategy for where to catch, per-item recovery with type guards, retries, result objects, validation at the edge with guard clauses, assertions for invariants, and reading a stack trace.

How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.

Before you start, make sure you can answer:

  • What a return inside finally does to a propagating exception; why catch (e) {} is dangerous.
  • TypeError versus RangeError versus SyntaxError versus ReferenceError; what a stack overflow is.
  • Why custom errors carry a code as well as a class; what cause is for; why JSON.stringify(err) is {}.
  • Where to catch (boundaries) and what the layers in between may do; why per-item recovery needs a type guard.
  • Number.isFinite versus typeof; validation versus assertion; how to read the top frame and column of a trace.

The programs are a transaction processor with a custom error hierarchy and all-or-nothing transfers, a configuration loader that wraps failures with cause and reports the chain, and an RPN calculator that raises the right error type for each kind of bad input.

Common questions

What does a return inside finally do to an exception?

It swallows it. A return in finally overrides whatever the try or catch was completing with, including a propagating exception, so the function returns normally and the error is lost without a trace.

What is the difference between TypeError, RangeError, SyntaxError and ReferenceError?

TypeError is a value of the wrong type for an operation; RangeError the right type but an impossible value, including a stack overflow in V8; SyntaxError text that does not parse, including bad JSON.parse input; ReferenceError a read of an undeclared name or of a variable in its temporal dead zone.

Why does per-item error recovery need a type guard?

Without one, a catch inside the loop also catches bugs such as a TypeError, and every record silently fails for the same defect. Guard with instanceof or a code: record expected failures and move on, but rethrow anything else so a bug aborts the batch loudly.

JavaScript Error Handling Quiz: Try, Catch and Custom Errors

Test JavaScript error handling with 12 questions and three programs: try, catch and finally, error types, custom errors with cause, validation, stack traces.

  • Course: JavaScript study plan
  • Module: Errors and error handling
  • Kind: Checkpoint — cleared at 70%
  • Reading time: 24 min
  • Runtime: Node 16

Checkpoint — Errors is the checkpoint that closes the Errors and error handling module: a graded quiz and whole-program exercises, passed at 70%.

Instructions

This checkpoint covers the mechanics of throw/try/catch/finally (including what finally overrides and when the stack is captured), the built-in error types and what triggers each, designing custom errors with name, code, fields and cause, the boundary strategy for where to catch, per-item recovery with type guards, retries, result objects, validation at the edge with guard clauses, assertions for invariants, and reading a stack trace.

How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.

Before you start, make sure you can answer:

  • What a return inside finally does to a propagating exception; why catch (e) {} is dangerous.
  • TypeError versus RangeError versus SyntaxError versus ReferenceError; what a stack overflow is.
  • Why custom errors carry a code as well as a class; what cause is for; why JSON.stringify(err) is {}.
  • Where to catch (boundaries) and what the layers in between may do; why per-item recovery needs a type guard.
  • Number.isFinite versus typeof; validation versus assertion; how to read the top frame and column of a trace.

The programs are a transaction processor with a custom error hierarchy and all-or-nothing transfers, a configuration loader that wraps failures with cause and reports the chain, and an RPN calculator that raises the right error type for each kind of bad input.

Common questions

What does a return inside finally do to an exception?

It swallows it. A return in finally overrides whatever the try or catch was completing with, including a propagating exception, so the function returns normally and the error is lost without a trace.

What is the difference between TypeError, RangeError, SyntaxError and ReferenceError?

TypeError is a value of the wrong type for an operation; RangeError the right type but an impossible value, including a stack overflow in V8; SyntaxError text that does not parse, including bad JSON.parse input; ReferenceError a read of an undeclared name or of a variable in its temporal dead zone.

Why does per-item error recovery need a type guard?

Without one, a catch inside the loop also catches bugs such as a TypeError, and every record silently fails for the same defect. Guard with instanceof or a code: record expected failures and move on, but rethrow anything else so a bug aborts the batch loudly.

Exercises

A transaction processor with all-or-nothing transfers

Using the starter's AppError, define AccountNotFound(id) (code E_NOT_FOUND, message account <id> not found), InvalidAmount(text) (code E_INVALID_AMOUNT, invalid amount <text> — for anything not a finite positive number) and InsufficientFunds(id, need, have) (code E_INSUFFICIENT, <id> has <have>, needs <need>). Commands: open <id> <amount>, deposit <id> <amount>, withdraw <id> <amount>, transfer <from> <to> <amount> — which must validate both accounts and the balance before changing anything, so a failed transfer leaves every balance untouched — and show (prints balances: id=balance ... in creation order). Print <code>: <message> for each AppError; rethrow anything else. End with errors: <code=count sorted by code> (or errors: none).

Example (excerpt): open ada 100, open bob 20, transfer ada bob 60, transfer ada cy 10, transfer bob ada 500, show →

E_NOT_FOUND: account cy not found
E_INSUFFICIENT: bob has 80, needs 500
balances: ada=40 bob=80
errors: E_INSUFFICIENT=1 E_NOT_FOUND=1

A config loader that keeps the cause

Each line is a JSON config. loadConfig(text) parses it (a SyntaxError is wrapped as ConfigError("config is not valid JSON", { cause })), requires a plain object (ConfigError("config must be an object") with a TypeError("got <null|array|typeof>") cause), then validates host (non-empty string, trimmed; TypeError("host must be a non-empty string, got <JSON>")), port (integer 1–65535; RangeError("port must be 1-65535, got <JSON>")) and retries (default 3; non-negative integer; RangeError("retries must be a non-negative integer, got <JSON>")) — each field failure wrapped as ConfigError("invalid config at <field>", { cause }). Print ok: host=<> port=<> retries=<> or error chain: <Name: message <- Name: message>, showing a SyntaxError by name only (its message differs between engines).

Example: {"host":"db.local","port":5432}, {"host":"x","port":70000}, {oops, [1,2] →

ok: host=db.local port=5432 retries=3
error chain: ConfigError: invalid config at port <- RangeError: port must be 1-65535, got 70000
error chain: ConfigError: config is not valid JSON <- SyntaxError
error chain: ConfigError: config must be an object <- TypeError: got array

An RPN calculator with typed failures

Evaluate each line as a reverse-Polish expression over + - * / and decimal numbers. Throw SyntaxError("unknown token '<t>'") for anything else, SyntaxError("not enough operands for '<op>'") when an operator finds fewer than two values, SyntaxError("too many operands: <n> left on the stack") when more than one value remains, and RangeError("division by zero"). Print <expression> = <result> or <name>: <message>; count every line in a finally and failures in the catch; end with evaluated=<n> failed=<m>.

Example: 3 4 +, 5 1 2 + 4 * + 3 -, 1 0 /, 1 +, 1 2 3, 2 x * →

3 4 + = 7
5 1 2 + 4 * + 3 - = 14
RangeError: division by zero
SyntaxError: not enough operands for '+'
SyntaxError: too many operands: 3 left on the stack
SyntaxError: unknown token 'x'
evaluated=6 failed=4

In this module: Errors and error handling

← Reading stack traces and decoding the errors you will see most · Callbacks and the event loop — one thread, two queues →