Desk Clarity

Everyday document & browser help

Python Tuple += Raises but the Inner List Changes: Inspect Partial Mutation

By ON Lab · Sources checked November 9, 2026

An exception does not imply rollback. The contained list can change before tuple item assignment fails. Inspect state after the exception before retrying.

Reproduce the boundary in a disposable example

A tuple item augmented assignment raises TypeError after changing its contained list.

bundle = (["draft"],)
try:
    bundle[0] += ["reviewed"]
except TypeError:
    pass
assert bundle == (["draft", "reviewed"],)
# Intentional mutation does not need to assign the tuple slot.
bundle[0].append("published")
assert bundle[0][-1] == "published"
# Or construct a new bundle without editing the old inner list.
original = (["draft"],)
replacement = (original[0] + ["reviewed"],)
assert original == (["draft"],)
assert replacement == (["draft", "reviewed"],)
print("partial mutation and explicit alternatives verified")

Read the result before changing application code

The first assertion belongs after the exception handler. Logging only the traceback would miss the state change. A retry of the same operation could append the same record again. Capture a safe snapshot of the affected data before deciding whether an operation can be retried.

Choose the behavior your caller needs

Use an explicit list method when shared mutable contents are intentional. Build new contents and a new container when callers need an unchanged original. For an immutable record contract, a tuple that contains a list is not enough: use immutable contents as well. Review callers holding a reference to the inner list; replacing the outer tuple does not update those references.

Scope and limits

The example demonstrates one built-in operation. It is not a claim that all exceptions have partial effects or that application-level transactions roll back Python object changes.

Related: compare the adjacent data or execution boundary.

The embedded example was executed in an isolated local Python process on November 9, 2026. It is a reproducible boundary check, not a test of your full application.

Sources