awesome-everything RU
↑ Back to the climb

Base CS from zero

Errors vs exceptions

Crux An error is a condition the program cannot handle in normal flow. An exception is the mechanism: when an error is raised, normal control flow stops and the runtime unwinds the call stack searching for a handler.
◷ 20 min

So far every program you have traced ran cleanly to the end. The program counter advanced, the call stack pushed and popped frames, and the program produced a result. But real programs hit conditions they were not built to continue past: a file that does not exist, a number divided by zero, a value of the wrong type.

When that happens, two different things are going on at once, and beginners mix them up. One is the bad situation itself — the missing file. The other is what the machine does about it — stop, and go looking for code that knows how to recover. This lesson keeps those two things strictly apart: the error (the condition) and the exception (the mechanism that responds to it).

Goal

After this lesson you can define an error as a condition the program cannot handle in normal flow, define an exception as the runtime mechanism that responds to a raised error, explain that raising an exception stops normal control flow and unwinds the call stack, and explain what a handler is and what happens when no handler is found.

1

An error is a condition, not an event in the machine. An error is a situation the program reaches that it cannot continue past using its normal logic. Examples: opening a file that does not exist, dividing a number by zero, reading a property from a value that has no properties, converting the text "hello" to a number.

The key word is condition. An error is a fact about the state of the program at a particular moment — the requested file is absent, the divisor is zero. It is not yet an action. Nothing has happened to the program counter or the call stack yet. The error is simply true: the program is now somewhere its normal flow has no defined next step.

2

An exception is the mechanism that responds to a raised error. When the program detects an error condition, it does not just stop silently. It raises an exception (in JavaScript and TypeScript the keyword is throw; “raise” and “throw” mean the same act). An exception is the runtime mechanism — recall the runtime from Unit 04, the support code that manages a program while it executes — that takes over the moment an error is raised.

So the error is the condition (“the file is missing”). The exception is the response (“stop normal flow, and start searching for code that can handle this”). One is a fact; the other is a process. A program can detect an error and choose to raise an exception about it — or detect the same error and handle it inline without any exception at all. The error does not force the mechanism; the mechanism is one possible response to it.

3

Raising an exception stops normal control flow. Recall from Unit 07 that normal control flow is the ordered sequence of instructions the CPU runs — straight down, with branches and loops steering the program counter. An exception breaks that.

The instant an exception is raised, the runtime stops normal control flow. The next line of the current function does not run. The program counter is no longer advancing through the program the way Unit 07 described. Control has been handed entirely to the exception mechanism, which now has one job: find code that knows what to do about this error. Until it finds that code — or runs out of places to look — no ordinary instruction of the program runs at all.

4

The runtime unwinds the call stack looking for a handler. Recall the call stack from Unit 08: a stack of frames, one per active function call, the most recent on top. When an exception is raised, the runtime walks down that stack, frame by frame, from the frame that raised the exception toward the program entry. This walk is called unwinding the stack.

At each frame, the runtime asks one question: does this function have a handler — a block of code written to catch this exception and recover (in JavaScript, a catch block)? If yes, unwinding stops there: the handler runs, normal control flow resumes from inside the handler, and the program continues. If no, the runtime pops that frame (exactly the pop from Unit 08 — the function is abandoned, its locals discarded) and moves to the frame below. The search continues downward until a handler is found.

5

If no handler exists anywhere, the program crashes. Suppose the runtime unwinds every frame — it pops the function that raised the exception, then its caller, then its caller — all the way down to the bottom frame, the program entry, and still finds no handler. There is nowhere left to look.

At that point the program crashes: the runtime terminates the program and prints a description of the unhandled exception, including the list of frames it unwound through. That printed list of frames is the stack trace, the subject of the next lesson. A crash is not the machine breaking — it is the exception mechanism reaching the bottom of the call stack with no handler, and giving up in a controlled, reported way.

main
entry
load
frame
parse
frame
THROW
frame
The call stack at the moment an exception is raised. parse called the function shown rightmost, which raised the exception (THROW, in rose). The runtime unwinds leftward — parse, then load, then main — popping each frame until it finds a handler. If main has none, the program crashes.
Worked example

Tracing one error from condition to crash.

A program reads a config file and parses a number from it. The call chain is mainloadConfigparseNumber.

1. The error condition arises. Inside parseNumber, the text from the file is "hello", and the code tries to convert it to a number. "hello" is not a number — this is the error condition. It is just a fact: the conversion has no defined result.

2. An exception is raised. parseNumber responds to that condition by raising an exception — throw new Error("not a number"). Normal control flow inside parseNumber stops immediately; the rest of parseNumber does not run.

3. The runtime unwinds. The runtime checks parseNumber’s frame for a handler — none. It pops parseNumber’s frame and moves to loadConfig’s frame. It checks loadConfig for a handler — none. It pops loadConfig’s frame and moves to main’s frame.

4a. With a handler. Suppose main has a catch block around the loadConfig call. Unwinding stops at main’s frame. The handler runs — perhaps it prints “using defaults” and continues. Normal control flow resumes inside main. No crash.

4b. Without a handler. Suppose main has no catch block. The runtime pops main’s frame too. The stack is now empty — there is nowhere left to search. The program crashes, printing the unhandled exception and the frames it unwound through.

The error condition was the same in both cases. What differed was whether the exception mechanism found a handler before reaching the bottom of the stack.

Why this works

Why separate the condition from the mechanism? Because they vary independently. The same error condition — a missing file — might be raised as an exception in one program and quietly handled with an if check in another. And the same mechanism — unwinding the stack to find a handler — responds to thousands of different error conditions in exactly the same way. Keeping the two ideas apart lets you reason about each one cleanly: “what went wrong” is a question about the condition; “what the program did next” is a question about the mechanism.

Common mistake

A common mistake is to think an exception is the error, so “an exception happened” means “something is broken.” Not so. An exception is just a control-flow mechanism — a disciplined way to stop and search for a handler. A well-written program can raise an exception, catch it in a handler, recover, and continue completely normally. The exception is only a problem if it reaches the bottom of the stack with nowhere to be caught.

Practice 0 / 5

An error is a condition; an exception is the mechanism that responds to it. Dividing by zero is which of the two — type 1 for the error condition, 2 for the mechanism?

An exception is raised inside parseNumber. parseNumber has no handler. Its caller loadConfig has no handler. main has a handler. How many frames does the runtime pop before unwinding stops?

main calls a which calls b. b raises an exception. No function anywhere has a handler. How many frames are on the call stack after the runtime finishes unwinding?

When an exception is raised, normal control flow stops. Does the next line of the function that raised the exception run? Type 1 for yes, 0 for no.

The runtime unwinds the call stack and reaches the bottom frame (program entry) without finding a handler. What happens to the program? Type 1 for it crashes, 0 for it continues normally.

Check yourself
Quiz

What is the difference between an error and an exception?

Recap

An error is a condition: a situation the program reaches that it cannot continue past with its normal logic — a missing file, a division by zero, a bad type conversion. An exception is a mechanism: when an error is raised (the throw keyword in JavaScript), the runtime stops normal control flow — the next line does not run — and unwinds the call stack, walking frame by frame from the frame that raised the exception down toward the program entry. At each frame it looks for a handler (a catch block). If it finds one, the handler runs and normal control flow resumes; if it unwinds the whole stack without finding one, the program crashes and prints the unhandled exception. The condition is the fact; the exception is the controlled response — keep the two ideas apart.

Continue the climb ↑The stack trace
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.