Skip to main content
ai-slop/python-mutable-defaultmanual fix

Mutable default argument.

A function parameter that defaults to `[]`, `{}`, or `set()`. Python evaluates the default once, so every call that omits the argument shares and mutates the same object.

Flagged shape and clean shape.

Each example shows the exact code shape the rule is looking for, then the smallest version that keeps the intent without hiding risk or adding noise.

python-mutable-default.py
✗ Flagged
def add_tag(tag, tags=[]):
    tags.append(tag)
    return tags

add_tag("a")  # ["a"]
add_tag("b")  # ["a", "b"]: the default list is shared
Why this trips

Deterministic signature parse: reads each `def` signature, including multi-line ones, with strings and comments masked, and flags a parameter whose default is `[]`, `{}`, or `set()`.

python-mutable-default.py
✓ Clean
def add_tag(tag, tags=None):
    tags = tags if tags is not None else []
    tags.append(tag)
    return tags
What changed

Default to `None` and create the value inside the body: `items = items if items is not None else []`.

Agents write the default they want each call to start with, which is how defaults behave in many other languages. In Python it leaks state between calls.

How this rule is justified.

Rule id

ai-slop/python-mutable-default

Enforcing engine

ai-slop

Detector strategy

Deterministic signature parse: reads each `def` signature, including multi-line ones, with strings and comments masked, and flags a parameter whose default is `[]`, `{}`, or `set()`.

Legitimate code that is NOT flagged

`None` defaults, immutable defaults such as tuples, and empty literals nested inside a call (for example FastAPI's `Query(default=[])`) are not flagged.

Evidence

Part of aislop's Python rule set, scored in the strict tier. v0.15.0 stopped flagging FastAPI, typer, and pydantic marker defaults.