UnboundLocalError: cannot access local variable 'total' where it is not associated with a value
Python · updated 2026-11-04
Raised when a function reads a name that Python treats as local (because the function assigns it somewhere) before any assignment has run. Older versions say "local variable 'x' referenced before assignment".
Traceback (most recent call last):
File "/app/billing.py", line 30, in <module>
print(invoice_total(lines))
File "/app/billing.py", line 14, in invoice_total
return total
^^^^^
UnboundLocalError: cannot access local variable 'total' where it is not associated with a valueQuick fix
Assign the variable before any branch that might skip it (total = 0 at the top), or make sure every if/elif/else and try/except path sets it. If you meant a module-level variable, pass it in as an argument instead of assigning to it inside the function.
- Find every place the function assigns the name; the read happens on a path where none of them ran.
- Initialize it at the top of the function with a sensible default.
- For try/except, set it before the try, or handle the except path explicitly.
- If the function assigns to a module-level name, Python treats it as local everywhere in that function: rename it, or pass and return the value.
def invoice_total(lines):
total = 0 # before: assigned only inside the loop
for line in lines:
total += line.qty * line.price
return total # safe even when lines is empty
def load_config(path):
config = {} # before: set only in the try block
try:
config = read_json(path)
except FileNotFoundError:
log.warning("no config at %s, using defaults", path)
return configWhy it happens
Assigned only inside a loop or branch
A variable set inside a for loop or an if block is unset when the loop has no items or the condition is false.
Assigned inside try, read after except
When the try block fails before the assignment and the except block does not set it, the code after the try reads an unset variable.
Shadowing a module-level name
count += 1 inside a function makes count local for the whole function, so reading it first fails even though a module-level count exists.
Other fixes
- Linters (pyright, pylint "possibly-used-before-assignment") catch most of these before the code runs.
- Use global or nonlocal only when you really intend to change an outer variable; passing values is usually clearer.
Same error, other wording
- UnboundLocalError: local variable 'total' referenced before assignment
- UnboundLocalError: cannot access local variable 'response' where it is not associated with a value
- NameError: free variable 'x' referenced before assignment in enclosing scope
Let your coding agent catch the next one
Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:
> Find the UnboundLocalError exceptions in production, show me each variable and the code path where it was never assigned, and initialize it or handle that path.
Related errors
- ReferenceError: x is not defined
- AttributeError: 'NoneType' object has no attribute 'x'
- KeyError: 'email'
References: Python docs: built-in exceptions (UnboundLocalError), Python FAQ: why do I get an UnboundLocalError