UnboundLocalError: cannot access local variable where it is not associated with a value in Python
Initialize the variable locally before conditional branches, pass it as a function parameter, or declare global var_name / nonlocal var_name if modifying outer scope variables.
Root Cause Analysis
This error occurs when Python tries to read a variable inside a function body, but Python's compiler classified that variable as local to the function because an assignment (=, +=, or :=) exists somewhere in the function scope, and the read operation occurred before the assignment was reached.
Python's LEGB Scope and Compile-Time Variable Binding
Python determines variable scope at compile time (when the function is defined), not at runtime. The rule is simple:
If a variable is assigned anywhere inside a function, Python marks it as a local variable for the entire function body.
Consider this classic trap:
count = 10
def increment():
count += 1 # count = count + 1
Because count = ... exists on the right side of +=, Python treats count as purely local. When it evaluates the left side count + 1, the local variable has not yet been bound to any value, raising UnboundLocalError: cannot access local variable 'count' where it is not associated with a value.
Common Scenarios
- Conditional Initialization: Reading
resultafter anif condition:block where theelse:branch was omitted. - Modifying Global Counters: Calling
counter += 1inside helper functions withoutglobal counter. - Closures & Nested Functions: Reassigning outer variables in inner functions without
nonlocal.
Reproduction Code (MCVE)
counter = 10
# Python marks 'counter' as local due to the assignment inside the conditional branch
def calculate(flag: bool = False):
if flag:
counter = 20
print(counter) # Reading unbound local variable raises UnboundLocalError
calculate()
Solution 1: Explicitly Initialize Local Variable or Pass as Argument
Pass values explicitly as function arguments or initialize default fallback values at the top of the function.
def calculate_safe(base_val: int = 10, flag: bool = False) -> int:
# Initialize locally at function entry point
result = base_val
if flag:
result = 20
return result
print(f'Default execution: {calculate_safe()}')
print(f'Flagged execution: {calculate_safe(flag=True)}')
Solution 2: Use `global` or `nonlocal` for State Modification
Use global for module-level variables or nonlocal for enclosing closure scopes.
def create_counter():
count = 0
def increment():
nonlocal count # Declares count belongs to outer enclosing scope
count += 1
return count
return increment
counter_fn = create_counter()
print(f'Counter step 1: {counter_fn()}')
print(f'Counter step 2: {counter_fn()}')
Common Pitfalls & Error Contrasts
Contrasting UnboundLocalError with NameError:
UnboundLocalError: Subclass ofNameError. The variable was detected as a local symbol by the compiler, but was read before assignment.NameError: name 'x' is not defined: The symbol does not exist in any scope (Local, Enclosing, Global, or Builtin).- Shadowing: Naming a local variable the same as a built-in (e.g.
list = [1, 2]) shadows the built-in function throughout the scope.