FAILURE MAP
← Case archive

FA-30031 / HTTP retries / Open access

Idempotency receipt expiry during retry: Eviction state violates retry transition semantics · case 01

Eviction state violates retry transition semantics

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

ROOT CAUSE

Eviction state violates retry transition semantics

VERIFIED REPAIR

Restore the specified transition records.pop(k); old=None.

Unsuccessful approach: The attempted repair changes the faulty site to records.pop(k); old=[None,now,False,None] but still violates a regression oracle.

Case contract

put(key,body,expires) creates a pending receipt if no live receipt exists at current logical time. Existing live matching key returns pending or cached; mismatched body returns conflict. commit succeeds only for a live pending receipt. at(time) moves monotonic time forward. Expiry at now is expired. lookup(key) reports missing/pending/cached. Return outcomes. Commit appends committed or ignored to expose whether a durable receipt write occurred.

Why this case matters

Offline deterministic model of HTTP request retries.

1 / The failure

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

N = 1
observations = []
def solve(events):
    now=0; records={}; out=[]
    for e in events:
        if e[0]=='at': now=max(now,e[1])
        elif e[0]=='put':
            k,body,expires=e[1:]
            old=records.get(k)
            if old is not None and old[1]<=now:
                records.pop(k); old=old
            if old is None:
                if expires<=now: out.append('expired'); continue
                records[k]=[body,expires,False,None]; out.append('new')
            elif old[0]!=body: out.append('conflict')
            elif old[2]: out.append(['cached',old[3]])
            else: out.append('pending')
        elif e[0]=='commit':
            old=records.get(e[1])
            if old is not None and old[1]>now and not old[2]:
                old[2]=True; old[3]=e[2]; out.append('committed')
            else: out.append('ignored')
        elif e[0]=='lookup':
            old=records.get(e[1])
            if old is None or old[1]<=now: out.append('missing')
            elif old[2]: out.append(['cached',old[3]])
            else: out.append('pending')
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([]), [])
check('1', solve([('lookup','x'),('put','a',N,3),('put','a',N,3),('commit','a',N+9),('commit','a',999),('lookup','a'),('put','a',N,3),('put','a',N+1,3)]), ['missing','new','pending','committed','ignored',['cached',N+9],['cached',N+9],'conflict'])
check('2', solve([('at',3),('put','a',N,3),('put','b',N,2)]), ['expired','expired'])
check('3', solve([('put','a',N,3),('at',3),('commit','a',99),('lookup','a'),('put','a',N+1,5),('lookup','a')]), ['new','ignored','missing','new','pending'])
check('4', solve([('at',4),('put','a',N,6),('at',6),('lookup','a')]), ['new','missing'])
check('5', solve([('put','a',N,2),('at',3),('at',1),('lookup','a')]), ['new','missing'])
check('6', solve([('commit','absent',N),('lookup','absent')]), ['ignored','missing'])
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
0[][]Passed
1['missing', 'new', 'pending', 'committed', 'ignored', ['cached', 10], ['cached', 10], 'conflict']['missing', 'new', 'pending', 'committed', 'ignored', ['cached', 10], ['cached', 10], 'conflict']Passed
2['expired', 'expired']['expired', 'expired']Passed
3['new', 'ignored', 'missing', 'conflict', 'missing']['new', 'ignored', 'missing', 'new', 'pending']Failed
4['new', 'missing']['new', 'missing']Passed
5['new', 'missing']['new', 'missing']Passed
6['ignored', 'missing']['ignored', 'missing']Passed

SHA-256 / 09c25b5ef4037f9ad08c80dca784365510f922613d6f68da8bb88f5046a2bf1b

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(events):
    now=0; records={}; out=[]
    for e in events:
        if e[0]=='at': now=max(now,e[1])
        elif e[0]=='put':
            k,body,expires=e[1:]
            old=records.get(k)
            if old is not None and old[1]<=now:
                records.pop(k); old=[None,now,False,None]
            if old is None:
                if expires<=now: out.append('expired'); continue
                records[k]=[body,expires,False,None]; out.append('new')
            elif old[0]!=body: out.append('conflict')
            elif old[2]: out.append(['cached',old[3]])
            else: out.append('pending')
        elif e[0]=='commit':
            old=records.get(e[1])
            if old is not None and old[1]>now and not old[2]:
                old[2]=True; old[3]=e[2]; out.append('committed')
            else: out.append('ignored')
        elif e[0]=='lookup':
            old=records.get(e[1])
            if old is None or old[1]<=now: out.append('missing')
            elif old[2]: out.append(['cached',old[3]])
            else: out.append('pending')
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([]), [])
check('1', solve([('lookup','x'),('put','a',N,3),('put','a',N,3),('commit','a',N+9),('commit','a',999),('lookup','a'),('put','a',N,3),('put','a',N+1,3)]), ['missing','new','pending','committed','ignored',['cached',N+9],['cached',N+9],'conflict'])
check('2', solve([('at',3),('put','a',N,3),('put','b',N,2)]), ['expired','expired'])
check('3', solve([('put','a',N,3),('at',3),('commit','a',99),('lookup','a'),('put','a',N+1,5),('lookup','a')]), ['new','ignored','missing','new','pending'])
check('4', solve([('at',4),('put','a',N,6),('at',6),('lookup','a')]), ['new','missing'])
check('5', solve([('put','a',N,2),('at',3),('at',1),('lookup','a')]), ['new','missing'])
check('6', solve([('commit','absent',N),('lookup','absent')]), ['ignored','missing'])
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
0[][]Passed
1['missing', 'new', 'pending', 'committed', 'ignored', ['cached', 10], ['cached', 10], 'conflict']['missing', 'new', 'pending', 'committed', 'ignored', ['cached', 10], ['cached', 10], 'conflict']Passed
2['expired', 'expired']['expired', 'expired']Passed
3['new', 'ignored', 'missing', 'conflict', 'missing']['new', 'ignored', 'missing', 'new', 'pending']Failed
4['new', 'missing']['new', 'missing']Passed
5['new', 'missing']['new', 'missing']Passed
6['ignored', 'missing']['ignored', 'missing']Passed

SHA-256 / 5032d3f9c9ae82ea078d275e5378f855e645e52658f11598f6765be5fc86c89f

3 / The verified repair

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

N = 1
observations = []
def solve(events):
    now=0; records={}; out=[]
    for e in events:
        if e[0]=='at': now=max(now,e[1])
        elif e[0]=='put':
            k,body,expires=e[1:]
            old=records.get(k)
            if old is not None and old[1]<=now:
                records.pop(k); old=None
            if old is None:
                if expires<=now: out.append('expired'); continue
                records[k]=[body,expires,False,None]; out.append('new')
            elif old[0]!=body: out.append('conflict')
            elif old[2]: out.append(['cached',old[3]])
            else: out.append('pending')
        elif e[0]=='commit':
            old=records.get(e[1])
            if old is not None and old[1]>now and not old[2]:
                old[2]=True; old[3]=e[2]; out.append('committed')
            else: out.append('ignored')
        elif e[0]=='lookup':
            old=records.get(e[1])
            if old is None or old[1]<=now: out.append('missing')
            elif old[2]: out.append(['cached',old[3]])
            else: out.append('pending')
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([]), [])
check('1', solve([('lookup','x'),('put','a',N,3),('put','a',N,3),('commit','a',N+9),('commit','a',999),('lookup','a'),('put','a',N,3),('put','a',N+1,3)]), ['missing','new','pending','committed','ignored',['cached',N+9],['cached',N+9],'conflict'])
check('2', solve([('at',3),('put','a',N,3),('put','b',N,2)]), ['expired','expired'])
check('3', solve([('put','a',N,3),('at',3),('commit','a',99),('lookup','a'),('put','a',N+1,5),('lookup','a')]), ['new','ignored','missing','new','pending'])
check('4', solve([('at',4),('put','a',N,6),('at',6),('lookup','a')]), ['new','missing'])
check('5', solve([('put','a',N,2),('at',3),('at',1),('lookup','a')]), ['new','missing'])
check('6', solve([('commit','absent',N),('lookup','absent')]), ['ignored','missing'])
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
0[][]Passed
1['missing', 'new', 'pending', 'committed', 'ignored', ['cached', 10], ['cached', 10], 'conflict']['missing', 'new', 'pending', 'committed', 'ignored', ['cached', 10], ['cached', 10], 'conflict']Passed
2['expired', 'expired']['expired', 'expired']Passed
3['new', 'ignored', 'missing', 'new', 'pending']['new', 'ignored', 'missing', 'new', 'pending']Passed
4['new', 'missing']['new', 'missing']Passed
5['new', 'missing']['new', 'missing']Passed
6['ignored', 'missing']['ignored', 'missing']Passed

SHA-256 / aba0cac156c38bf6144172a6872debb1334951fa4c0faca744649e01ee90e8bb

Verification & scope

Stipulated bounded simulator, not a complete HTTP implementation or a standards conformance claim. 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:41:48.954282+00:00.

Case digest / 06ac440c7c7f9c73190edebc24d3417fde9bb8dfa7491a182e64a9b9937ccac1