AssertionError, what it means and how to fix it

An assert statement is a checkpoint the programmer placed deliberately: “this must be true here; if it is not, stop.” AssertionError is the stop. When it carries no message, the traceback line itself is the information, pointing at the exact assumption that failed. In test suites the same exception is how frameworks like pytest report a failed comparison, dressed up with the values involved.

What it looks like

def withdraw(balance, amount):
    assert amount <= balance, "overdraft"
    return balance - amount

withdraw(50, 80)

Traceback (most recent call last):
  File "main.py", line 5, in <module>
AssertionError: overdraft

The fix, in order

  1. Find the assert and read its condition as a claim about the program. Something upstream produced a state the author believed impossible. Print the values in the condition just before the assert to see the actual state.
  2. Decide whether the data or the assumption is wrong. Either the input violated a precondition the function was entitled to (the caller's bug), or the assert encodes an assumption that stopped being true as the code evolved (the assert's bug). Both are common; the values tell you which.
  3. In tests, read the comparison the framework shows. pytest and unittest expand the failing assert with the actual values on each side. The fix is in whichever side's expectation mismatches the intended behavior; change the code or the test, deliberately, not whichever is quicker.
  4. Do not use assert for input validation in production code. Python's -O flag strips asserts entirely, so validation written as assert silently vanishes under optimization, and user input is exactly what asserts are not for. Raise real exceptions (ValueError, TypeError) for checks that must always run.
  5. Add messages to your own asserts. assert x > 0 failing tells you where; assert x > 0, f"x was {x}" tells you why. Future debugging time is bought here.

If it still happens

An assert that fires only under concurrency or after long uptime marks a state that degrades: resources exhausted, caches stale, counters wrapped. Reproduce by logging the asserted values with timestamps over time rather than rerunning once, since a single fresh run will pass and teach nothing.

Common questions

Why does my AssertionError have no message at all? Because the assert was written without one: assert condition raises a bare AssertionError. The useful evidence is the traceback itself, the line and the code it shows. Adding a message (or the values) at the assert is the improvement to make while you are there.

Can I catch AssertionError and recover? You can, but for your own asserts it defeats the purpose: they exist to halt on states the program does not know how to handle. Catch it at a boundary if you must (to log and exit cleanly), not to continue past a broken assumption.

Related errors

RuntimeError · NotImplementedError · ValueError: invalid literal for int()