Error Handling
Fundamentals Chapter 10 wrapped await fetch(...) in try/catch without explaining the mechanism fully. This chapter covers throw, the complete try/catch/finally structure, and — using Chapter 3's class/extends syntax — how to build custom error types carrying more information than a plain message string.
throw — Raising an Error Deliberately
throw new Error("message") immediately stops the current function (and everything that called it) from continuing normally — unlike Go's error return values (a deliberate contrast worth knowing if the Go course is ever revisited), JavaScript errors propagate upward automatically until something explicitly catches them.
try/catch — Catching a Thrown Error
Code inside try { } runs normally until something throws — at that exact point, execution jumps straight into catch (error) { }, skipping anything remaining in the try block. error.message holds the text passed to new Error(...); every error also has a name property ("Error" by default).
finally — Runs No Matter What
finally { } runs after try/catch complete, regardless of whether an error occurred — useful for cleanup work (hiding a loading spinner, closing a connection) that needs to happen either way. This is conceptually similar to Go's defer from the Go Intermediate course, just scoped specifically to error handling rather than every function exit.
Custom Error Classes
class ValidationError extends Error (Chapter 3's inheritance, applied to the built-in Error type) creates a genuinely new error type carrying extra structured data — here, field — alongside the standard message. super(message) must run first, exactly as with any other subclass constructor, to set up Error's own internal behaviour (including the stack trace).
Distinguishing Error Types in a catch Block
error instanceof ValidationError checks whether the caught error is specifically that custom type (or a subclass of it) — this is JavaScript's rough equivalent of Go's errors.As from the Go Advanced course, letting a catch block react differently depending on exactly what went wrong, rather than treating every error identically.
instanceof, a single catch block treats a genuine validation problem the same as an unrelated bug (a typo causing a TypeError, for instance) — both get silently swallowed and handled identically. Checking the specific error type before deciding how to respond avoids masking real bugs as if they were expected validation failures.
| Piece | Purpose |
|---|---|
| throw new Error("msg") | Deliberately raise an error, halting normal execution |
| try { } catch (e) { } | Run code; if it throws, jump to catch instead of crashing |
| finally { } | Always runs after try/catch, error or not — for cleanup |
| class X extends Error | Define a custom error type with extra data fields |
| error instanceof X | Check which specific error type was actually caught |
Coding Challenges
Write a function parsePositiveNumber(value) that throws a plain Error if value is negative or not a number (use isNaN), otherwise returns it. Call it inside a try/catch with a value that triggers the error, logging the caught message.
📄 View solutionDefine a custom error class InsufficientFundsError extending Error, with a constructor taking (message, shortfall) and storing shortfall. Write a function withdraw(balance, amount) that throws it if amount > balance, including the shortfall (amount - balance). Catch it and log a message using error.shortfall.
📄 View solutionWrite a function riskyOperation(shouldFail) that throws a RangeError if shouldFail is true, otherwise returns "Success". Wrap a call in try/catch/finally: log the result or the error's name+message in catch, and always log "Operation complete" in finally, regardless of outcome. Call it twice, once with each boolean.
📄 View solutionChapter 5 Quick Reference
- throw new Error("message") — deliberately raises an error, halting normal flow
- try { } catch (error) { } — catches a thrown error instead of letting it crash the program
- finally { } — always runs after try/catch, error or not
- error.message — the text passed when the error was created; error.name — its type name
- class X extends Error — custom error type; must call super(message) first
- error instanceof X — checks the specific error type caught, for differentiated handling
- Built-in error types: Error, TypeError, RangeError, SyntaxError, and more
- Next chapter: array/object copying — shallow vs deep, and common mutation pitfalls