UnboundLocalError: local variable referenced before assignment — how to fix
Traceback (most recent call last):
File "app.py", line 7, in <module>
increment()
File "app.py", line 4, in increment
count += 1
UnboundLocalError: local variable 'count' referenced before assignment
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value
Quick fix: If you meant the module-level variable, add global count (or nonlocal count in a nested function) at the top of the function — or better, pass it in and return the new value. If a branch can skip the assignment, initialise the variable first (e.g. result = None) before the if/try/for.
What it means
Python decides whether a name is local when the function is compiled, not line by line. If a function assigns to a name anywhere in its body (x = ..., x += ..., for x in, import x, except E as x, with ... as x), that name is local throughout the entire function. Reading it before an assignment has executed raises UnboundLocalError.
Python 3.11+ words it as cannot access local variable 'x' where it is not associated with a value. Same error.
Cause 1: modifying a global inside a function
count = 0
def increment():
count += 1 # UnboundLocalError
count += 1 is an assignment, so count is local, and reading the local before it's set fails. Options:
# Option A: declare it global
def increment():
global count
count += 1
# Option B (cleaner): pass and return
def increment(count):
return count + 1
count = increment(count)
For mutable state, a class or a dict avoids global entirely:
state = {"count": 0}
def increment():
state["count"] += 1 # mutating, not rebinding: no error
Cause 2: nested functions / closures
def make_counter():
total = 0
def add():
total += 1 # UnboundLocalError
return total
return add
Use nonlocal to rebind the enclosing function's variable:
def add():
nonlocal total
total += 1
return total
Cause 3: assignment only in some branches
def grade(score):
if score >= 50:
result = "pass"
elif score >= 0:
result = "fail"
return result # error when score < 0
Initialise before branching, or add an else:
def grade(score):
result = None
if score >= 50:
result = "pass"
elif score >= 0:
result = "fail"
return result
Same with try/except: if the try fails before assignment, the variable doesn't exist afterwards.
try:
data = load()
except IOError:
log.warning("load failed")
print(data) # UnboundLocalError if load() raised
Set data = None before try, or return/raise in the except.
And with loops: a for loop over an empty iterable never assigns the loop variable.
Cause 4: shadowing a global or import later in the function
import os
def main():
print(os.getcwd()) # UnboundLocalError
import os # this makes 'os' local for all of main()
Likewise, a later len = 5 makes len local and breaks an earlier len(x). Remove the late assignment or rename the variable.
Cause 5: except ... as e is deleted after the block
e = None
try:
1 / 0
except ZeroDivisionError as e:
pass
print(e) # NameError/UnboundLocalError: 'e' is deleted at end of except
Python deletes e when the except block ends. Copy it: except ZeroDivisionError as exc: err = exc.
Last updated 2026-11-02.