Python
UnboundLocalError
Error Handling
Programming
Debugging

How can I fix UnboundLocalError local variable referenced before assignment?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

UnboundLocalError in Python means code tries to read a local variable before it gets assigned in that function scope. It often appears when a variable name is reused unintentionally or assignment happens only in one branch. The fix is to make scope and initialization explicit.

Why This Error Happens

Python decides variable scope at function compile time. If a variable is assigned anywhere in a function, Python treats it as local in that function.

Example that fails:

python
1x = 10
2
3def f():
4    print(x)   # tries local x
5    x = 20     # assignment makes x local
6
7f()

Because x is local inside f, print(x) reads it before assignment.

Fix with Explicit Initialization

Initialize local variable before use.

python
1def compute_total(items):
2    total = 0
3    for value in items:
4        total += value
5    return total

This avoids branch-dependent uninitialized state.

Fix Branch-Dependent Assignment

A common bug is assigning only inside one condition.

python
1def status_label(score):
2    if score >= 50:
3        label = "pass"
4    else:
5        label = "fail"
6    return label

Always assign in all branches before returning or reading.

Use global Only When Intentional

If you truly need to write global variable from function, declare global explicitly.

python
1counter = 0
2
3def increment():
4    global counter
5    counter += 1

Use this sparingly. Global mutation often makes code harder to reason about.

Use nonlocal in Nested Functions

Nested closures can trigger similar errors when inner function writes outer variable.

python
1def make_counter():
2    count = 0
3
4    def inc():
5        nonlocal count
6        count += 1
7        return count
8
9    return inc

Without nonlocal, assignment creates new local variable and read-before-assign errors can appear.

Refactor to Reduce Scope Confusion

Large functions with reused names are more error-prone. Refactor into smaller functions and pass values explicitly.

A practical pattern:

  • Compute value in one function.
  • Return it explicitly.
  • Avoid reading mutable outer state unless necessary.

This reduces accidental variable shadowing.

Watch Out for try and except Paths

Assignments inside try block can be skipped if exception occurs.

python
1def parse_number(text):
2    value = None
3    try:
4        value = int(text)
5    except ValueError:
6        pass
7    return value

Pre-initializing value avoids unbound local errors after exceptions.

Debugging Checklist

When this error appears:

  1. Find variable named in exception.
  2. Search all assignments to that name in function.
  3. Confirm assignment happens before first read on every path.
  4. Check nested scope and global or nonlocal usage.
  5. Rename variables to avoid shadowing outer names.

This sequence usually identifies root cause quickly.

Preventive Practices

Use linters and type checkers. Tools like ruff or pylint often flag potential unbound local usage before runtime.

Also keep function scope narrow and naming explicit. Style discipline prevents many scope bugs.

Comprehension and Closure Edge Cases

Scope confusion can also happen in closures and loops that capture variables. If closure behavior seems inconsistent, inspect captured names and initialization order carefully.

python
funcs = []
for i in range(3):
    funcs.append(lambda x, i=i: x + i)

Binding loop variable explicitly in lambda defaults avoids unexpected late-binding behavior that is often mistaken for scope bugs.

Common Pitfalls

  • Reading variable before assignment in same function scope.
  • Assigning variable in only one conditional branch.
  • Forgetting nonlocal in nested function updates.
  • Mutating global state unintentionally.
  • Reusing outer variable names and causing shadowing confusion.

Summary

  • 'UnboundLocalError is a scope and initialization issue.'
  • Assign local variables before any read on all code paths.
  • Use global and nonlocal only when intentional.
  • Refactor large functions to reduce shadowing and scope complexity.
  • Use linters to catch scope bugs early.

Course illustration
Course illustration

All Rights Reserved.