FAILURE MAP
← Case archive

FA-29521 / HTTP retries / Open access

Nested client retry ownership: Retry ownership metadata names the wrong layer · case 01

Retry ownership metadata names the wrong layer

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

ROOT CAUSE

Retry ownership metadata names the wrong layer

VERIFIED REPAIR

Restore the specified transition ['retry',owner[0]].

Unsuccessful approach: The attempted repair changes the faulty site to ['retry',None] but still violates a regression oracle.

Case contract

enter(layer, allowance) pushes a retry scope. A child with any ancestor delegates retry to the oldest scope and never spends its local cap. fail returns retry/exhausted charged to oldest scope. leave pops the current scope; success clears every scope. Return decision pairs and remaining scope budgets.

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):
    stack=[]; out=[]
    for e in events:
        if e[0]=='enter':
            stack.append([e[1],e[2],0])
        elif e[0]=='leave':
            if stack: stack.pop()
        elif e[0]=='success':
            stack.clear()
        elif e[0]=='fail':
            if not stack:
                out.append(['unowned',None]); continue
            owner=stack[0]
            if owner[2]>=owner[1]:
                out.append(['exhausted',owner[0]])
            else:
                owner[2]+=1
                out.append(['retry',stack[-1][0]])
    return [out,stack]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([]), [[],[]])
check('1', solve([('fail',)]), [[['unowned',None]],[]])
check('2', solve([('enter','outer',2),('enter','inner',9),('fail',),('fail',),('fail',)]), [[['retry','outer'],['retry','outer'],['exhausted','outer']],[['outer',2,2],['inner',9,0]]])
check('3', solve([('enter','only',N),('fail',)]), [[['retry','only']],[['only',N,1]]])
check('4', solve([('enter','outer',1),('enter','inner',1),('leave',),('fail',)]), [[['retry','outer']],[['outer',1,1]]])
check('5', solve([('enter','a',0),('enter','b',N),('success',),('fail',)]), [[['unowned',None]],[]])
check('6', solve([('enter','a',0),('fail',),('leave',),('leave',)]), [[['exhausted','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 fixtureActualExpectedOutcome
0[[], []][[], []]Passed
1[[['unowned', None]], []][[['unowned', None]], []]Passed
2[[['retry', 'inner'], ['retry', 'inner'], ['exhausted', 'outer']], [['outer', 2, 2], ['inner', 9, 0]]][[['retry', 'outer'], ['retry', 'outer'], ['exhausted', 'outer']], [['outer', 2, 2], ['inner', 9, 0]]]Failed
3[[['retry', 'only']], [['only', 1, 1]]][[['retry', 'only']], [['only', 1, 1]]]Passed
4[[['retry', 'outer']], [['outer', 1, 1]]][[['retry', 'outer']], [['outer', 1, 1]]]Passed
5[[['unowned', None]], []][[['unowned', None]], []]Passed
6[[['exhausted', 'a']], []][[['exhausted', 'a']], []]Passed

SHA-256 / 3e3b8d23b11c1a35ed4493defddc6c63dccd385127b83a248b89f6e61e3ba023

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(events):
    stack=[]; out=[]
    for e in events:
        if e[0]=='enter':
            stack.append([e[1],e[2],0])
        elif e[0]=='leave':
            if stack: stack.pop()
        elif e[0]=='success':
            stack.clear()
        elif e[0]=='fail':
            if not stack:
                out.append(['unowned',None]); continue
            owner=stack[0]
            if owner[2]>=owner[1]:
                out.append(['exhausted',owner[0]])
            else:
                owner[2]+=1
                out.append(['retry',None])
    return [out,stack]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([]), [[],[]])
check('1', solve([('fail',)]), [[['unowned',None]],[]])
check('2', solve([('enter','outer',2),('enter','inner',9),('fail',),('fail',),('fail',)]), [[['retry','outer'],['retry','outer'],['exhausted','outer']],[['outer',2,2],['inner',9,0]]])
check('3', solve([('enter','only',N),('fail',)]), [[['retry','only']],[['only',N,1]]])
check('4', solve([('enter','outer',1),('enter','inner',1),('leave',),('fail',)]), [[['retry','outer']],[['outer',1,1]]])
check('5', solve([('enter','a',0),('enter','b',N),('success',),('fail',)]), [[['unowned',None]],[]])
check('6', solve([('enter','a',0),('fail',),('leave',),('leave',)]), [[['exhausted','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 fixtureActualExpectedOutcome
0[[], []][[], []]Passed
1[[['unowned', None]], []][[['unowned', None]], []]Passed
2[[['retry', None], ['retry', None], ['exhausted', 'outer']], [['outer', 2, 2], ['inner', 9, 0]]][[['retry', 'outer'], ['retry', 'outer'], ['exhausted', 'outer']], [['outer', 2, 2], ['inner', 9, 0]]]Failed
3[[['retry', None]], [['only', 1, 1]]][[['retry', 'only']], [['only', 1, 1]]]Failed
4[[['retry', None]], [['outer', 1, 1]]][[['retry', 'outer']], [['outer', 1, 1]]]Failed
5[[['unowned', None]], []][[['unowned', None]], []]Passed
6[[['exhausted', 'a']], []][[['exhausted', 'a']], []]Passed

SHA-256 / e28739961240a088e01639b8425dcca270f68cca760f1fd35238c4d0cbf12023

3 / The verified repair

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

N = 1
observations = []
def solve(events):
    stack=[]; out=[]
    for e in events:
        if e[0]=='enter':
            stack.append([e[1],e[2],0])
        elif e[0]=='leave':
            if stack: stack.pop()
        elif e[0]=='success':
            stack.clear()
        elif e[0]=='fail':
            if not stack:
                out.append(['unowned',None]); continue
            owner=stack[0]
            if owner[2]>=owner[1]:
                out.append(['exhausted',owner[0]])
            else:
                owner[2]+=1
                out.append(['retry',owner[0]])
    return [out,stack]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('0', solve([]), [[],[]])
check('1', solve([('fail',)]), [[['unowned',None]],[]])
check('2', solve([('enter','outer',2),('enter','inner',9),('fail',),('fail',),('fail',)]), [[['retry','outer'],['retry','outer'],['exhausted','outer']],[['outer',2,2],['inner',9,0]]])
check('3', solve([('enter','only',N),('fail',)]), [[['retry','only']],[['only',N,1]]])
check('4', solve([('enter','outer',1),('enter','inner',1),('leave',),('fail',)]), [[['retry','outer']],[['outer',1,1]]])
check('5', solve([('enter','a',0),('enter','b',N),('success',),('fail',)]), [[['unowned',None]],[]])
check('6', solve([('enter','a',0),('fail',),('leave',),('leave',)]), [[['exhausted','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 fixtureActualExpectedOutcome
0[[], []][[], []]Passed
1[[['unowned', None]], []][[['unowned', None]], []]Passed
2[[['retry', 'outer'], ['retry', 'outer'], ['exhausted', 'outer']], [['outer', 2, 2], ['inner', 9, 0]]][[['retry', 'outer'], ['retry', 'outer'], ['exhausted', 'outer']], [['outer', 2, 2], ['inner', 9, 0]]]Passed
3[[['retry', 'only']], [['only', 1, 1]]][[['retry', 'only']], [['only', 1, 1]]]Passed
4[[['retry', 'outer']], [['outer', 1, 1]]][[['retry', 'outer']], [['outer', 1, 1]]]Passed
5[[['unowned', None]], []][[['unowned', None]], []]Passed
6[[['exhausted', 'a']], []][[['exhausted', 'a']], []]Passed

SHA-256 / 048e1a057db3094c6f347897dd4e56eb50b6e8fc629d0b04d5de6513b1857145

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:44.011322+00:00.

Case digest / 2588d0c08ad536f052c5a9fb6fbf3d508e86e64dca64ffab12721c3b9401960a