Bug Squash
Eight broken Python functions. Fix each one until the hidden tests pass.
How to play
Each level gives you a function that looks right and a short description of what it is supposed to do. Something in it is wrong. Edit the code in the editor, press Run tests, and the hidden assertions run against your version on a real Python interpreter. A test that fails tells you what it expected, so you can work backwards from the symptom — exactly the loop you will use on your own code for the rest of your programming life.
You do not have to match our fix. Any code that passes every test counts.
The eight bugs, and why they matter
- Inverted condition.
n % 2 == 1where== 0was meant. One character; completely wrong behaviour. - Off-by-one.
range(1, n)stops beforen. The single most common loop bug in any language. - Missing return. The function computes the answer and throws it away, so callers get
None. - Type clash.
"Age: " + ageraisesTypeError— an f-string fixes it. - Mutable default argument. The default list is created once at definition time and shared by every call.
- IndexError. Looping to
len(items) + 1walks one square past the end of the list. - Bad initial value. A maximum finder that starts at
0silently breaks on all-negative input — the nastiest kind of bug, because it only fails for some inputs. - KeyError.
counts[word] += 1assumes the key already exists;counts.get(word, 0) + 1does not.
Every one of these is drawn from our list of 15 common Python errors and how to fix them, which explains the error messages in more depth.
A debugging method that works
- Read the failing test first. It names the input and the expected output — half the diagnosis.
- Predict before you run. Say what you think the current code does for that input, then check. When the prediction is wrong, you have found your misunderstanding, not just the bug.
- Change one thing at a time. Two simultaneous fixes make it impossible to tell which worked.
- Test the boundaries. Empty list, single item, zero, negative numbers — that is where these bugs hide.
Frequently asked questions
What is the Bug Squash game?
Eight small Python functions, each containing one realistic bug — an off-by-one error, a mutable default argument, a missing return, a KeyError. You edit the code and press Run tests; the tests execute as real Python and show you which ones pass.
Do the tests really run Python?
Yes. Your fixed function and the test assertions are executed on CPython compiled to WebAssembly, in a background worker, so a passing test means the code genuinely works.
Can I see the solution?
After three unsuccessful runs a Show solution button appears. Use the hint first — the point is the moment of spotting it yourself.
Which bugs are included?
Inverted modulo logic, an off-by-one range, a missing return statement, string-plus-int TypeError, the mutable default argument trap, an IndexError from len() + 1, a max-finder that breaks on negative numbers, and a dictionary KeyError when counting.
Why practise debugging specifically?
Because it is most of the job. Beginners spend far more time fixing code than writing it, and the bugs here are the ones that actually recur — they come straight from our guide to the 15 most common Python errors.