Say you write a small function and run it. Python stops and prints this:
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value It feels wrong. You did create count, right at the top of your file. On Python 3.10 and older, the same error reads local variable 'count' referenced before assignment. Same error, same causes. I tested every example below on Python 3.11, 3.12 and 3.14. All three print the newer wording. I couldn't test anything older.
What the Error Means
Before a function runs, Python reads the whole body and decides which names are local. The rule is short. Assign to a name anywhere in the function, and that name is local everywhere in it, from the first line to the last. Read it before the assignment has run and there's no value yet. That's your UnboundLocalError.
Reading a Global Is Fine
Only assigning causes trouble. This function just reads count, so Python happily uses the global one:
count = 5 def show(): return count + 1 print(show()) It prints 6. Add an assignment to count inside the function and things change. Python makes it local, and the global disappears from view. Every cause below is a version of that.
The Six Causes
1. count = count + 1 Inside a Function
count = 0 def add(): count = count + 1 return count print(add()) The line count = count + 1 assigns to count, so count is local in add(). Then the right-hand side reads that local one, which has no value yet. The best fix is to skip the global entirely. Pass the value in and return the new one.
count = 0 def add(count): return count + 1 count = add(count) print(count) There's a quick fix too. Put global count inside the function and Python knows you mean the global variable. It works. But now the function changes something outside itself, and that gets hard to follow as your program grows:
count = 0 def add(): global count count = count + 1 return count print(add()) 2. total += n
total = 0 def add(n): total += n return total print(add(5)) total += n is shorthand for total = total + n. So it assigns to total and makes it local. Most people hit the error this way, since += doesn't look like an assignment. Pass the running total in and return the new one:
total = 0 def add(total, n): return total + n total = add(total, 5) print(total) 3. The Variable Is Only Assigned Inside an if
def describe(score): if score >= 50: result = "pass" return result print(describe(80)) print(describe(10)) describe(80) works, so the bug is easy to miss. Try describe(10). The if is skipped, result never gets assigned, and the return blows up. Give the variable a value on every path:
def describe(score): if score >= 50: result = "pass" else: result = "fail" return result print(describe(80)) print(describe(10)) 4. You Use It Above the Line That Assigns It
def show(): print(name) name = "Emre" show() The assignment to name is on line two, so name is local from line one. The print runs first, before there's any value. Move the assignment up, or pick a different name for what you want to print.
def show(): name = "Emre" print(name) show() 5. The Variable Is Only Assigned Inside a Loop
def last_item(items): for item in items: last = item return last print(last_item([1, 2, 3])) print(last_item([])) Give it a list with items and last gets a value. Give it an empty list and the loop body never runs, so last stays unassigned. Set a starting value before the loop:
def last_item(items): last = None for item in items: last = item return last print(last_item([1, 2, 3])) print(last_item([])) You'll see this one in real programs a lot. The empty case is the one nobody tests.
6. An Inner Function Changes an Outer Variable
def counter(): n = 0 def inc(): n += 1 return n return inc tick = counter() print(tick()) Inside inc(), n += 1 makes n local to inc(). It isn't the n from counter(). When the variable lives in an enclosing function, you need nonlocal, not global:
def counter(): n = 0 def inc(): nonlocal n n += 1 return n return inc tick = counter() print(tick()) print(tick()) Things That Count as Assignment Without Looking Like It
Four more statements make a name local to the whole function, and none of them has an equals sign. Read the name above any of them and you get the same error. I tested each one. Each raised UnboundLocalError:
| Statement | What to do |
|---|---|
import os inside the function, below a use of os | Move the import to the top of the file |
for i in range(3): below a read of i | Use a different loop variable |
with open(...) as f: below a read of f | Use a different name for the file |
except ... as err: and then err used after the block | Copy what you need out of the exception first |
The except case catches most people off guard. Python deletes the exception variable on purpose when the except block ends. So touching it afterwards fails:
def run(): try: 1 / 0 except ZeroDivisionError as err: pass print(err) # Python deletes err when the except block ends run() While you're still inside the block, copy what you need into another variable:
def run(): message = None try: 1 / 0 except ZeroDivisionError as err: message = str(err) # copy what you need before the block ends print(message) run() It prints division by zero.
Which Cause Is It?
| The line that fails | Cause | Fix |
|---|---|---|
x = x + 1 or x += 1 in a function | The name becomes local | Pass it in and return it, or global x |
A return or print of a variable set inside an if | A path never assigns it | Assign on every path |
| A use that comes above the assignment | Used before assigned | Move the assignment up |
A variable set only inside a for or while | The loop may not run | Set a starting value first |
x += 1 in an inner function | Local to the inner function | nonlocal x |
The Rule, Stated Once
Assign to a name anywhere in a function and it's local to the whole function. So give it a value before you read it. If you really mean a variable from outside, say so with global (module level) or nonlocal (enclosing function). Even better, pass values in and return them.
New to Python? Start with Python for Beginners and Python modules. For more Python errors with a clear fix, try ModuleNotFoundError After pip install, Tkinter TclError: Image Doesn’t Exist and Why Your Tkinter App Freezes.
Download the code: the broken and fixed versions of all six causes are on GitHub in Python-projects/Troubleshooting/unboundlocalerror. Run any file with python bug.py from inside its folder.
Originally published on my blog. I post new C, Python and AI-agent guides there regularly.