Home โบ Errors โบ UnboundLocalError
UnboundLocalError: your global just became local
Exception: UnboundLocalErrorCategory: runtime (call time)Raised at: the first line inside a function that reads a name the compiler already marked local
What this error means
UnboundLocalError is Python telling you that a name is local to this function, but no value has been bound to it yet on this particular path. The confusing part: the name may well exist as a global and work perfectly one line earlier in the file. Inside the function it is a different, still-empty slot.
The rule that causes almost every case: Python decides local-vs-global when it compiles the function, not while it runs. If the word count appears on the left of an = anywhere in the function body โ even on the very last line, even inside an if that never runs โ the compiler marks count local for the entire function. Every earlier read of count in that function then hits an empty local slot and raises.
UnboundLocalError is a subclass of NameError, so except NameError catches it. The wording changed in Python 3.11: older versions said local variable 'count' referenced before assignment, newer versions say cannot access local variable 'count' where it is not associated with a value. Same bug.
A real example
count = 0
def increment():
print(count) # line 4
count = count + 1 # line 5 โ this line makes count local
increment()
Traceback (most recent call last):
File "demo.py", line 7, in <module>
increment()
File "demo.py", line 4, in increment
print(count)
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value
Line 4 looks innocent โ count is 0 at module level and prints fine outside the function. But because line 5 assigns to count, the compiler already declared it local, so line 4 reads the local slot before anything was stored there. Deleting line 5 makes the crash disappear, which is what makes this error feel random.
The three ways to fix it
- Declare it global โ add
global countas the first statement in the function. Now the assignment writes to the module-level name instead of creating a local one. Correct, but the function now mutates state the caller cannot see from the signature; prefer the next option for anything beyond a counter. - Pass it in and return it โ
def increment(count): return count + 1, thencount = increment(count). No scoping tricks, obvious data flow, and the function is testable. This is the fix to reach for first. - Initialise the local before you read it โ if the name was only ever meant to be local, put
count = 0at the top of the function and drop the global entirely.
For a nested function that assigns to a name owned by the enclosing function (not a module global), global is wrong โ use nonlocal:
def counter():
total = 0
def bump():
nonlocal total # without this line: UnboundLocalError
total += 1
return total
return bump
The conditional-assignment variant
The same error appears with no global in sight when an assignment sits inside a branch that does not always run. The compiler still marks the name local, so the path that skips the assignment reads an empty slot:
def high_values(nums):
for n in nums:
if n > 100:
biggest = n
return biggest # crashes when every n <= 100
Traceback (most recent call last):
File "demo.py", line 7, in <module>
print(high_values([4, 18, 55]))
File "demo.py", line 5, in high_values
return biggest
UnboundLocalError: cannot access local variable 'biggest' where it is not associated with a value
The fix is to give the name a value on every path โ biggest = None before the loop, or better, return a value that cannot be confused with data (return max(nums, default=None)).
How to debug it
- Search the whole function body for the reported name on the left of
=,+=, in afor x in ...header, in animport, or as a parameter. Any one of those is what made it local. - Check for a
try/exceptwhere the assignment lives in thetryand the read in theexceptโ a failed assignment leaves the local unbound. - Ask which scope should own the name. Module state โ
global. Enclosing function state โnonlocal. Really local โ initialise it first. - Run
python -m pdb yourfile.pyand usewplusp countat the failing line: an unbound local reports*** NameErroreven though the global prints fine withp globals()['count']. - If the name is a common word (
total,result,data,id,type), consider that a parameter or a later line reused it by accident โ rename one of them.
Fix it interactively
These free problems are the same scope bug in disguise โ repair them in the browser:
Practice more Python bugs โRelated messages worth knowing
- NameError โ the parent exception โ same root cause, raised when the name is missing from every scope.
- Functions and scope โ the local / enclosing / global / built-in lookup order that decides this.
- The full Python errors guide โ every common traceback in one place.
๐ฎ๐ณ Hindi เคฎเฅเค เคธเคฎเคเฅเค
Python function ko compile karte waqt hi decide kar leta hai ki kaunsa naam local hai. Agar function ke andar kahin bhi count = ... likha hai โ chahe last line par ho, chahe ek if ke andar jo kabhi chalta hi nahi โ to count poore function ke liye local ban jata hai. Isliye usse pehle wali line jab count padhti hai, slot khaali hota hai aur UnboundLocalError milta hai, bhale hi bahar global count = 0 defined ho. Teen fix hain: function ke andar sabse pehle global count likho; ya behtar โ value ko argument bhejo aur return karwao (def increment(count): return count + 1); ya local ko pehle initialise kar do. Nested function me enclosing variable ke liye global nahi, nonlocal chahiye.