FA-29886 / HTTP retries / Open access
Retry budget reservation lifecycle: Held idempotency violates retry transition semantics · case 01
Held idempotency violates retry transition semantics
ROOT CAUSE
Held idempotency violates retry transition semantics
VERIFIED REPAIR
Restore the specified transition if e[1] in held: out.append('held'); continue.
Unsuccessful approach: The attempted repair changes the faulty site to if e[1] in held: out.append('denied'); continue but still violates a regression oracle.
Case contract
configure(capacity) resets a shared retry pool. reserve(request) consumes one token only for a new reservation; commit spends its token and removes the reservation, abort refunds exactly once, refill is capped. Repeated reserve is idempotent; unknown commit/abort does nothing. Return admissions and available token count.
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):
capacity=0; available=0; held=set(); out=[]
for e in events:
if e[0]=='configure':
capacity=e[1]; available=capacity; held.clear()
elif e[0]=='reserve':
if False: out.append('held'); continue
if available==0: out.append('denied'); continue
available-=1
held.add(e[1])
out.append('reserved')
elif e[0]=='commit':
if e[1] in held:
held.remove(e[1])
elif e[0]=='abort':
if e[1] in held:
held.remove(e[1])
available=min(capacity,available+1)
elif e[0]=='refill':
available=min(capacity-len(held),available+e[1])
return [out,available,sorted(held)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([('configure',3),('reserve','a'),('reserve','b'),('abort','a')]), [['reserved','reserved'],2,['b']])
check('1', solve([('configure',3),('reserve','a'),('commit','a'),('reserve','a'),('commit','a'),('reserve','a'),('commit','a'),('refill',2)]), [['reserved','reserved','reserved'],2,[]])
check('2', solve([]), [[],0,[]])
check('3', solve([('configure',0),('reserve','a')]), [['denied'],0,[]])
check('4', solve([('configure',2),('reserve','a'),('reserve','a'),('reserve','b'),('reserve','c')]), [['reserved','held','reserved','denied'],0,['a','b']])
check('5', solve([('configure',3),('reserve','a'),('reserve','b'),('commit','a'),('abort','a'),('abort','b'),('abort','b')]), [['reserved','reserved'],2,[]])
check('6', solve([('configure',N+3),('reserve','a'),('refill',N+10)]), [['reserved'],N+2,['a']])
check('7', solve([('configure',4),('reserve','a'),('commit','a'),('reserve','b'),('commit','b'),('refill',1)]), [['reserved','reserved'],3,[]])
check('8', solve([('configure',1),('reserve','a'),('configure',2),('reserve','a')]), [['reserved','reserved'],1,['a']])
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 0 | [['reserved', 'reserved'], 2, ['b']] | [['reserved', 'reserved'], 2, ['b']] | Passed |
| 1 | [['reserved', 'reserved', 'reserved'], 2, []] | [['reserved', 'reserved', 'reserved'], 2, []] | Passed |
| 2 | [[], 0, []] | [[], 0, []] | Passed |
| 3 | [['denied'], 0, []] | [['denied'], 0, []] | Passed |
| 4 | [['reserved', 'reserved', 'denied', 'denied'], 0, ['a']] | [['reserved', 'held', 'reserved', 'denied'], 0, ['a', 'b']] | Failed |
| 5 | [['reserved', 'reserved'], 2, []] | [['reserved', 'reserved'], 2, []] | Passed |
| 6 | [['reserved'], 3, ['a']] | [['reserved'], 3, ['a']] | Passed |
| 7 | [['reserved', 'reserved'], 3, []] | [['reserved', 'reserved'], 3, []] | Passed |
| 8 | [['reserved', 'reserved'], 1, ['a']] | [['reserved', 'reserved'], 1, ['a']] | Passed |
SHA-256 / 0687dba08b9d295a4d6ae60b239d726efb03773b969210a4f50775b3242e4ea4
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
capacity=0; available=0; held=set(); out=[]
for e in events:
if e[0]=='configure':
capacity=e[1]; available=capacity; held.clear()
elif e[0]=='reserve':
if e[1] in held: out.append('denied'); continue
if available==0: out.append('denied'); continue
available-=1
held.add(e[1])
out.append('reserved')
elif e[0]=='commit':
if e[1] in held:
held.remove(e[1])
elif e[0]=='abort':
if e[1] in held:
held.remove(e[1])
available=min(capacity,available+1)
elif e[0]=='refill':
available=min(capacity-len(held),available+e[1])
return [out,available,sorted(held)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([('configure',3),('reserve','a'),('reserve','b'),('abort','a')]), [['reserved','reserved'],2,['b']])
check('1', solve([('configure',3),('reserve','a'),('commit','a'),('reserve','a'),('commit','a'),('reserve','a'),('commit','a'),('refill',2)]), [['reserved','reserved','reserved'],2,[]])
check('2', solve([]), [[],0,[]])
check('3', solve([('configure',0),('reserve','a')]), [['denied'],0,[]])
check('4', solve([('configure',2),('reserve','a'),('reserve','a'),('reserve','b'),('reserve','c')]), [['reserved','held','reserved','denied'],0,['a','b']])
check('5', solve([('configure',3),('reserve','a'),('reserve','b'),('commit','a'),('abort','a'),('abort','b'),('abort','b')]), [['reserved','reserved'],2,[]])
check('6', solve([('configure',N+3),('reserve','a'),('refill',N+10)]), [['reserved'],N+2,['a']])
check('7', solve([('configure',4),('reserve','a'),('commit','a'),('reserve','b'),('commit','b'),('refill',1)]), [['reserved','reserved'],3,[]])
check('8', solve([('configure',1),('reserve','a'),('configure',2),('reserve','a')]), [['reserved','reserved'],1,['a']])
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 0 | [['reserved', 'reserved'], 2, ['b']] | [['reserved', 'reserved'], 2, ['b']] | Passed |
| 1 | [['reserved', 'reserved', 'reserved'], 2, []] | [['reserved', 'reserved', 'reserved'], 2, []] | Passed |
| 2 | [[], 0, []] | [[], 0, []] | Passed |
| 3 | [['denied'], 0, []] | [['denied'], 0, []] | Passed |
| 4 | [['reserved', 'denied', 'reserved', 'denied'], 0, ['a', 'b']] | [['reserved', 'held', 'reserved', 'denied'], 0, ['a', 'b']] | Failed |
| 5 | [['reserved', 'reserved'], 2, []] | [['reserved', 'reserved'], 2, []] | Passed |
| 6 | [['reserved'], 3, ['a']] | [['reserved'], 3, ['a']] | Passed |
| 7 | [['reserved', 'reserved'], 3, []] | [['reserved', 'reserved'], 3, []] | Passed |
| 8 | [['reserved', 'reserved'], 1, ['a']] | [['reserved', 'reserved'], 1, ['a']] | Passed |
SHA-256 / 7a96fd2d427140b7d0b09a031dae515b4cc5e8ba39f32c9a2498ddb4007ad9fe
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
capacity=0; available=0; held=set(); out=[]
for e in events:
if e[0]=='configure':
capacity=e[1]; available=capacity; held.clear()
elif e[0]=='reserve':
if e[1] in held: out.append('held'); continue
if available==0: out.append('denied'); continue
available-=1
held.add(e[1])
out.append('reserved')
elif e[0]=='commit':
if e[1] in held:
held.remove(e[1])
elif e[0]=='abort':
if e[1] in held:
held.remove(e[1])
available=min(capacity,available+1)
elif e[0]=='refill':
available=min(capacity-len(held),available+e[1])
return [out,available,sorted(held)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([('configure',3),('reserve','a'),('reserve','b'),('abort','a')]), [['reserved','reserved'],2,['b']])
check('1', solve([('configure',3),('reserve','a'),('commit','a'),('reserve','a'),('commit','a'),('reserve','a'),('commit','a'),('refill',2)]), [['reserved','reserved','reserved'],2,[]])
check('2', solve([]), [[],0,[]])
check('3', solve([('configure',0),('reserve','a')]), [['denied'],0,[]])
check('4', solve([('configure',2),('reserve','a'),('reserve','a'),('reserve','b'),('reserve','c')]), [['reserved','held','reserved','denied'],0,['a','b']])
check('5', solve([('configure',3),('reserve','a'),('reserve','b'),('commit','a'),('abort','a'),('abort','b'),('abort','b')]), [['reserved','reserved'],2,[]])
check('6', solve([('configure',N+3),('reserve','a'),('refill',N+10)]), [['reserved'],N+2,['a']])
check('7', solve([('configure',4),('reserve','a'),('commit','a'),('reserve','b'),('commit','b'),('refill',1)]), [['reserved','reserved'],3,[]])
check('8', solve([('configure',1),('reserve','a'),('configure',2),('reserve','a')]), [['reserved','reserved'],1,['a']])
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 0 | [['reserved', 'reserved'], 2, ['b']] | [['reserved', 'reserved'], 2, ['b']] | Passed |
| 1 | [['reserved', 'reserved', 'reserved'], 2, []] | [['reserved', 'reserved', 'reserved'], 2, []] | Passed |
| 2 | [[], 0, []] | [[], 0, []] | Passed |
| 3 | [['denied'], 0, []] | [['denied'], 0, []] | Passed |
| 4 | [['reserved', 'held', 'reserved', 'denied'], 0, ['a', 'b']] | [['reserved', 'held', 'reserved', 'denied'], 0, ['a', 'b']] | Passed |
| 5 | [['reserved', 'reserved'], 2, []] | [['reserved', 'reserved'], 2, []] | Passed |
| 6 | [['reserved'], 3, ['a']] | [['reserved'], 3, ['a']] | Passed |
| 7 | [['reserved', 'reserved'], 3, []] | [['reserved', 'reserved'], 3, []] | Passed |
| 8 | [['reserved', 'reserved'], 1, ['a']] | [['reserved', 'reserved'], 1, ['a']] | Passed |
SHA-256 / 7697ed66b0cd8c4c97edc64b0a4a54e1223e32323ce614329d3eea4f2672b5ce
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:47.584111+00:00.
Case digest / 4a2f124a3553305c8e0214300423861abf30a35b619ba669b5f9cd10a429f2d2