Bug

Common Python Bugs — Real Examples and Fixes

Python's dynamic nature makes certain bugs extremely common — and easy to miss in code review. These are the bugs that appear most frequently in Python production code, with working examples and exact fixes.


What is a Python bug?

A Python bug is any code defect that causes incorrect behavior at runtime. Unlike compiled languages, Python won't catch most bugs until the specific code path is executed — making thorough testing and static analysis essential.


1

NoneType AttributeError

Accessing attributes or methods on a value that is None. Python's most frequent runtime error.

❌ Crashes when name is None

user = get_user(id)
print(user.name.upper())  # AttributeError if user is None or user.name is None

✅ Safe with optional chaining

user = get_user(id)
print(user.name.upper() if user and user.name else "Unknown")
# Or with walrus operator (Python 3.8+):
if name := user and user.name:
    print(name.upper())
2

Mutable Default Argument

Using a mutable object (list, dict, set) as a default parameter value. Shared state across all calls.

❌ List shared between calls

def add_tag(tag, tags=[]):
    tags.append(tag)
    return tags

add_tag("python")  # ['python']
add_tag("django")  # ['python', 'django'] — NOT ['django']!

✅ None sentinel pattern

def add_tag(tag, tags=None):
    if tags is None:
        tags = []   # New list created for each call
    tags.append(tag)
    return tags
3

Off-by-One in Range / Slicing

Python's range() is exclusive at the end. Forgetting this causes off-by-one errors in loops and slices.

❌ Missing last item

items = [10, 20, 30, 40, 50]
for i in range(0, len(items) - 1):  # ← Missing last item (50)
    process(items[i])

# Also: slice [1:3] returns indexes 1 and 2, NOT 3

✅ Correct range usage

items = [10, 20, 30, 40, 50]
for i in range(len(items)):    # 0,1,2,3,4 — all items
    process(items[i])

# Even better — iterate directly:
for item in items:
    process(item)
4

Catching Too-Broad Exceptions

Using bare except: or except Exception: hides bugs and makes debugging impossible.

❌ Hides all errors silently

try:
    data = fetch_data()
    result = process(data)
except:           # ← Catches EVERYTHING including KeyboardInterrupt
    pass          # Bug? Network error? You'll never know.

✅ Specific exception handling

try:
    data = fetch_data()
    result = process(data)
except requests.ConnectionError as e:
    logger.error(f"Network error: {e}")
    raise
except ValueError as e:
    logger.error(f"Invalid data: {e}")
    return None
5

Integer Division Surprise (Python 2 → 3)

Python 3 uses true division for / but code migrated from Python 2 may have unexpected behavior.

❌ Unexpected float result

total = 7
count = 2
average = total / count   # 3.5 in Python 3 (was 3 in Python 2)
# If you expected integer division:
page = offset / page_size  # Should use //

✅ Explicit integer division

average = total / count     # 3.5 — float division
page    = offset // page_size  # 3   — integer (floor) division
remainder = offset % page_size # remainder
💡

Pro tip: Run mypy --strict on your codebase and pylint with default settings. Together they catch 70%+ of common Python bugs before runtime.


Detect Python Bugs Automatically

Paste your code — LearnCodeGuide detects all these issues automatically using GPT-4o + Claude Sonnet. Free to start.

Analyze Python Code →

Related Guides

NoneType ErrorMutable Default ArgumentIndex Out of RangePython Code Review GuidePython Bug Detector

Published by LearnCodeGuide Team · Last reviewed: October 2025