FAILURE MAP
← Case archive

FA-286 / Runtime and resources / Open access

Mutation changes what an established iterator visits · case 01

Inserting, deleting or replacing source elements alters an iteration that promised a stable snapshot.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The iterator retains the live collection or just its original length, rather than the original values.

VERIFIED REPAIR

Capture the sequence at iterator creation and yield those captured values while mutations affect only the source.

Unsuccessful approach: Remembering the initial length prevents visiting appended items but still reads shifted or replaced live values.

Case contract

Initial is a list of immutable scalar values. Edits are [yield index,operation,position,value] applied immediately before that snapshot yield. Operations append/delete/replace/insert/clear have valid positions at application time. Return [yielded original values,mutated source]. No yields means no scheduled edits execute. This is a shallow scalar snapshot, not object-graph isolation.

Why this case matters

Models stable observer iteration over a collection mutated by callbacks, with explicit separation between snapshot membership and the final state of the source collection.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, edits):
    source, snapshot, yielded, index = list(initial), list(initial), [], 0
    while index < len(source):
        for step, kind, position, value in edits:
            if step != index:
                continue
            if kind == 'append':
                source.append(value)
            elif kind == 'delete':
                del source[position]
            elif kind == 'replace':
                source[position] = value
            elif kind == 'insert':
                source.insert(position, value)
            elif kind == 'clear':
                source.clear()
        yielded.append(source[index] if index < len(source) else None)
        index += 1
    return [yielded, source]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
initial = list(range(N+2))
check('appended element is not visited', solve(initial, [[0, 'append', 0, 99]]), [initial, initial+[99]])
check('deleting first cannot skip original', solve(initial, [[0, 'delete', 0, None]]), [initial, initial[1:]])
check('replacement does not rewrite snapshot', solve(initial, [[0, 'replace', 0, 99]]), [initial, [99]+initial[1:]])
check('insertion does not repeat original', solve(initial, [[0, 'insert', 0, 99]]), [initial, [99]+initial])
check('clear still yields captured values', solve(initial, [[0, 'clear', 0, None]]), [initial, []])
check('empty iterator never invokes callbacks', solve([], [[0, 'append', 0, 99]]), [[], []])
check('no mutation preserves order', solve(initial, []), [initial, initial])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
appended element is not visited[[0, 1, 2, 99], [0, 1, 2, 99]][[0, 1, 2], [0, 1, 2, 99]]Failed
deleting first cannot skip original[[1, 2], [1, 2]][[0, 1, 2], [1, 2]]Failed
replacement does not rewrite snapshot[[99, 1, 2], [99, 1, 2]][[0, 1, 2], [99, 1, 2]]Failed
insertion does not repeat original[[99, 0, 1, 2], [99, 0, 1, 2]][[0, 1, 2], [99, 0, 1, 2]]Failed
clear still yields captured values[[None], []][[0, 1, 2], []]Failed
empty iterator never invokes callbacks[[], []][[], []]Passed
no mutation preserves order[[0, 1, 2], [0, 1, 2]][[0, 1, 2], [0, 1, 2]]Passed

SHA-256 / a82e71d4f86a42163295afc5171ef766b548e48583ca73a67eb9d11ac8e0f295

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, edits):
    source, snapshot, yielded, index = list(initial), list(initial), [], 0
    while index < len(snapshot):
        for step, kind, position, value in edits:
            if step != index:
                continue
            if kind == 'append':
                source.append(value)
            elif kind == 'delete':
                del source[position]
            elif kind == 'replace':
                source[position] = value
            elif kind == 'insert':
                source.insert(position, value)
            elif kind == 'clear':
                source.clear()
        yielded.append(source[index] if index < len(source) else None)
        index += 1
    return [yielded, source]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
initial = list(range(N+2))
check('appended element is not visited', solve(initial, [[0, 'append', 0, 99]]), [initial, initial+[99]])
check('deleting first cannot skip original', solve(initial, [[0, 'delete', 0, None]]), [initial, initial[1:]])
check('replacement does not rewrite snapshot', solve(initial, [[0, 'replace', 0, 99]]), [initial, [99]+initial[1:]])
check('insertion does not repeat original', solve(initial, [[0, 'insert', 0, 99]]), [initial, [99]+initial])
check('clear still yields captured values', solve(initial, [[0, 'clear', 0, None]]), [initial, []])
check('empty iterator never invokes callbacks', solve([], [[0, 'append', 0, 99]]), [[], []])
check('no mutation preserves order', solve(initial, []), [initial, initial])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
appended element is not visited[[0, 1, 2], [0, 1, 2, 99]][[0, 1, 2], [0, 1, 2, 99]]Passed
deleting first cannot skip original[[1, 2, None], [1, 2]][[0, 1, 2], [1, 2]]Failed
replacement does not rewrite snapshot[[99, 1, 2], [99, 1, 2]][[0, 1, 2], [99, 1, 2]]Failed
insertion does not repeat original[[99, 0, 1], [99, 0, 1, 2]][[0, 1, 2], [99, 0, 1, 2]]Failed
clear still yields captured values[[None, None, None], []][[0, 1, 2], []]Failed
empty iterator never invokes callbacks[[], []][[], []]Passed
no mutation preserves order[[0, 1, 2], [0, 1, 2]][[0, 1, 2], [0, 1, 2]]Passed

SHA-256 / 5acae9ab63bbb0dc125eab574482c895739209dff559f525e69b2afbc3f1de43

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, edits):
    source, snapshot, yielded, index = list(initial), list(initial), [], 0
    while index < len(snapshot):
        for step, kind, position, value in edits:
            if step != index:
                continue
            if kind == 'append':
                source.append(value)
            elif kind == 'delete':
                del source[position]
            elif kind == 'replace':
                source[position] = value
            elif kind == 'insert':
                source.insert(position, value)
            elif kind == 'clear':
                source.clear()
        yielded.append(snapshot[index])
        index += 1
    return [yielded, source]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
initial = list(range(N+2))
check('appended element is not visited', solve(initial, [[0, 'append', 0, 99]]), [initial, initial+[99]])
check('deleting first cannot skip original', solve(initial, [[0, 'delete', 0, None]]), [initial, initial[1:]])
check('replacement does not rewrite snapshot', solve(initial, [[0, 'replace', 0, 99]]), [initial, [99]+initial[1:]])
check('insertion does not repeat original', solve(initial, [[0, 'insert', 0, 99]]), [initial, [99]+initial])
check('clear still yields captured values', solve(initial, [[0, 'clear', 0, None]]), [initial, []])
check('empty iterator never invokes callbacks', solve([], [[0, 'append', 0, 99]]), [[], []])
check('no mutation preserves order', solve(initial, []), [initial, initial])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
appended element is not visited[[0, 1, 2], [0, 1, 2, 99]][[0, 1, 2], [0, 1, 2, 99]]Passed
deleting first cannot skip original[[0, 1, 2], [1, 2]][[0, 1, 2], [1, 2]]Passed
replacement does not rewrite snapshot[[0, 1, 2], [99, 1, 2]][[0, 1, 2], [99, 1, 2]]Passed
insertion does not repeat original[[0, 1, 2], [99, 0, 1, 2]][[0, 1, 2], [99, 0, 1, 2]]Passed
clear still yields captured values[[0, 1, 2], []][[0, 1, 2], []]Passed
empty iterator never invokes callbacks[[], []][[], []]Passed
no mutation preserves order[[0, 1, 2], [0, 1, 2]][[0, 1, 2], [0, 1, 2]]Passed

SHA-256 / 572d8a27b438efc366dbd38333311f075e177b47fbae315bc1062dc78c39a440

Verification & scope

This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:36:52.031230+00:00.

Case digest / 05523f0f8c57c528286898345060b29fd20335c633ee082b47567c835de47e25