UnboundLocalError: local variable referenced before assignment (Fix)
Fix the Python error UnboundLocalError: local variable referenced before assignment. This page explains what the error means, why Python raises it inside functions, and the safest ways to fix it.
Quick fix
count = 10
def show_count():
print(count) # works because we only read the global value
show_count()
If you assign to a variable anywhere inside a function, Python treats it as local in that function. Use a parameter, return value, or global/nonlocal only when appropriate.
What this error means
UnboundLocalError means:
- Python thinks the variable is local to the current function
- Your code tries to use that local variable before it gets a value
- This often happens when you read a variable first and assign to it later in the same function
A common example looks like this:
count = 10
def show_count():
print(count)
count = 20
show_count()
This raises an error because count = 20 makes Python treat count as a local variable inside show_count(). Then print(count) tries to read that local variable before it has been assigned.
Why Python raises this error
Python decides variable scope for a function when it reads the function body.
If a function assigns to a variable, Python marks that name as local for the whole function.
That means this code fails:
message = "Hello"
def greet():
print(message)
message = "Hi"
greet()
Even though message exists outside the function, Python sees message = "Hi" and treats message as local inside greet().
This is different from NameError:
UnboundLocalError: the variable is treated as local, but used before assignmentNameError: the variable name does not exist at all
If function scope feels unclear, see Python functions explained.
Example that causes the error
A very common case is trying to update a global variable inside a function without global.
total = 0
def add_one():
total = total + 1
return total
add_one()
Error:
UnboundLocalError: local variable 'total' referenced before assignment
Why it happens:
total = total + 1assigns tototal- So Python treats
totalas local inadd_one() - But the right side tries to read
totalbefore the local variable has a value
Another common case is assigning in only one branch:
def check_score(score):
if score >= 50:
result = "pass"
print(result)
check_score(20)
If score is less than 50, result never gets assigned.
Fix 1: Pass the value into the function
Use a parameter instead of relying on an outer variable.
This is usually the clearest fix for beginners.
def show_count(count):
print(count)
show_count(10)
Output:
10
This works well because:
- the function gets everything it needs directly
- it is easier to test
- it avoids hidden dependence on outer variables
If you are new to this idea, see function parameters and arguments in Python.
Fix 2: Return the new value
Instead of changing an outer variable inside the function, let the function return a value.
def add_one(total):
return total + 1
total = 0
total = add_one(total)
print(total)
Output:
1
This is often the best fix because:
- the function is predictable
- it avoids hidden changes
- the flow of data is easier to understand
If needed, review return values in Python functions.
Fix 3: Use global only when you really need it
global tells Python that you want to use the module-level variable.
total = 0
def add_one():
global total
total = total + 1
add_one()
print(total)
Output:
1
This fixes the error because total is no longer treated as a local variable inside the function.
Be careful with global:
- it can make code harder to follow
- many functions changing the same global variable can cause bugs
- passing values and returning results is often cleaner
Use global only if you really want to change a module-level variable.
Fix 4: Use nonlocal in nested functions
nonlocal is for variables in an enclosing function, not the global scope.
Use it when an inner function needs to update a variable from the outer function.
def outer():
count = 0
def inner():
nonlocal count
count += 1
print(count)
inner()
inner()
outer()
Output:
1
2
Without nonlocal, Python would treat count inside inner() as a new local variable and raise UnboundLocalError.
Fix 5: Make sure every code path assigns a value
Sometimes the variable is only assigned inside an if block or try block.
Set a default value before the conditional logic.
Example with if
def check_score(score):
result = "fail"
if score >= 50:
result = "pass"
print(result)
check_score(20)
check_score(80)
Output:
fail
pass
Example with try
def read_number(text):
number = None
try:
number = int(text)
except ValueError:
print("Not a valid number")
return number
print(read_number("25"))
print(read_number("abc"))
Output:
25
Not a valid number
None
If you use try blocks often, see using try, except, else, and finally in Python.
How to debug it step by step
When you see this error, work through these steps:
- Find the line named in the traceback.
- Check whether the variable is assigned anywhere in that function.
- Look for code like
print(variable)beforevariable = .... - Check if assignment happens only in some branches.
- Decide whether the variable should be:
- local
- global
- passed in as a parameter
- returned from the function
Useful debugging commands:
python your_script.py
print(variable_name)
print(locals())
print(globals().get("variable_name"))
What these help with:
print(variable_name)shows the current value if it existsprint(locals())shows local variables inside the functionprint(globals().get("variable_name"))checks the global value safely
For a broader beginner walkthrough, see the beginner guide to debugging Python code.
Related errors to compare
This error is often confused with other errors.
NameError
NameError: name is not defined happens when Python cannot find the variable at all.
UnboundLocalError vs NameError
If the message is confusing, it helps to compare the two directly. UnboundLocalError means the name is considered local but has no value yet. NameError means the name does not exist in the current scope.
Other errors after a bad quick fix
If you change your code in the wrong way, you might start seeing:
AttributeErrorTypeError
For example, if a variable becomes None or a different type than expected, a new error may appear even though UnboundLocalError is gone.
Common causes
Here are the most common reasons this error appears:
- Reading a global variable inside a function and assigning to it later
- Assigning a variable only inside an
ifblock - Assigning a variable only inside a
tryblock - Updating an outer variable inside a nested function without
nonlocal - Using the same variable name for both outer and local values
FAQ
Is UnboundLocalError the same as NameError?
No. UnboundLocalError means Python treats the name as local in the function, but you used it before assigning a value. NameError means the name was not found at all.
Why does this happen even if the variable exists outside the function?
Because assigning to that name inside the function makes Python treat it as a local variable for the whole function body.
Should I use global to fix it?
Only if you really want to change a module-level variable. In many cases, passing arguments and returning values is a better fix.
When should I use nonlocal?
Use nonlocal only inside nested functions when you need to change a variable from the enclosing function.