Skip to main content
CodeFlow
control flow~12 minRoute 01 11 of 12

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

Fail loudly. Catch only what you can recover from. A try/except that quietly swallows everything is how silent bugs are born.

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

An exception unwinds frames until something catches it. If nothing catches, the program ends. Catch only what you can actually do something about.

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"))  # None

Recover says

Don't catch generic Exception just to silence errors. Bugs hidden under empty catch blocks are the worst kind — silent, surviving, wrong.

Quiz it — make it stick

  1. Question 1

    When is `try / except Exception: pass` (or its equivalent in any language) usually a bad idea?

  2. True or false — Question 2

    In Go, exceptions are the standard way to signal a problem.

  3. Predict — Question 3

    In Python, what does this print?

    try:
        print("a")
        raise ValueError
        print("b")
    except ValueError:
        print("c")
    finally:
        print("d")

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.