Errors & Exceptions
When something goes wrong — fail loudly, recover where it makes sense.
Prerequisites:Conditions & BooleansFunctions
Story — when something goes wrong
Sooner or later your program asks for a file that doesn't exist, divides by zero, parses "twenty" as a number. The honest answer is there is no answer. Returning a fake one (zero, empty string, null) is what produces the bugs three tickets from now where someone wonders why total spend is suddenly negative.
Modern languages give you two patterns for this: exceptions (raise a special kind of value that unwinds the call stack until something catches it) and error returns (Go-style: the function returns the error alongside the result, and the caller chooses what to do). Same intent, different ergonomics.
Recover says
See it — raise, catch, propagate
When code raises (or throws), execution stops in the current function. The runtime walks up the call stack looking for a matching handler. If it finds one, that block runs and execution continues from there. If not, the program ends with the error printed. finally blocks run no matter what — that's where you close files and release locks.
✎ Sharpen your pencil
In one sentence, why is "catch and ignore" usually a bug?
Recover says
Try it — catch what you can fix
Exercise. You're writing a CSV importer that validates each row. Which of these belong inside a try/except, and which belong outside?
- (a) Parsing a row's numeric column.
- (b) Reading the file from disk.
- (c) The for-loop walking the rows.
Reveal answer
(a) and (b) belong inside try/except — both can fail in expected ways and you can recover (skip the row, show the user a message). (c) does not — wrapping a loop in a single try/except means one bad row aborts the whole file. Put the try inside the loop, around (a). Read the file once, with its own try around (b).
Code it — five languages, two patterns
Python, JavaScript, Java, C++ all use throw / try / catch. Go takes a different path — errors are values, returned alongside results. Both shapes solve the same problem.
def parse_age(s):
try:
n = int(s)
except ValueError:
return None # caller can handle missing
if n < 0:
raise ValueError("age cannot be negative")
return n
print(parse_age("21")) # 21
print(parse_age("twenty")) # NoneRecover says
Quiz it — make it stick
No Dumb Questions
Real questions other learners asked on this page.
What's the difference between an error and an exception?
Casual usage: interchangeable. Strict (Java-flavoured): "errors" are catastrophic (OutOfMemoryError) — don't catch them. "Exceptions" are recoverable (FileNotFoundException) — catch when you have a plan.Should I always wrap risky code in try/catch?
Only when you have something useful to do — log, retry, fall back, ask the user. Otherwise let it propagate. A try/catch with no real handling adds noise without value.What is "finally" for?
Cleanup that must happen whether or not an exception fired — close files, release locks, restore state. Modern languages also have "with"/"using"/"defer" for the same purpose.