FAILURE MAP
← Case archive

FA-4471 / Borrow checking / Open access

Shared borrow excludes writer · case 01

The operation returns a result or retained state that violates this contract: A single local object grants either any number of shared borrows or one exclusive borrow. Commands are [operation,token,value]. Reads return the value or denied; writes and acquisitions return booleans. Ownership can move only with no borrows. A shared borrow requires a live object, no exclusive borrower, and a fresh token.

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

ROOT CAUSE

A shared borrow requires a live object, no exclusive borrower, and a fresh token. The broken transition violates that invariant.

VERIFIED REPAIR

A single local object grants either any number of shared borrows or one exclusive borrow. Commands are [operation,token,value]. Reads return the value or denied; writes and acquisitions return booleans. Ownership can move only with no borrows. A shared borrow requires a live object, no exclusive borrower, and a fresh token.

Unsuccessful approach: The attempted transition changes the behavior but still violates the same invariant in at least one independent regression fixture.

Case contract

A single local object grants either any number of shared borrows or one exclusive borrow. Commands are [operation,token,value]. Reads return the value or denied; writes and acquisitions return booleans. Ownership can move only with no borrows. A shared borrow requires a live object, no exclusive borrower, and a fresh token. Inputs are the finite Python values shown by the executable fixtures; no concurrent execution is assumed.

Why this case matters

A controlled local-runtime regression for collection APIs, language semantics, or ownership wrappers. Fixtures include boundary and interaction cases.

1 / The failure

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

N = 1
observations = []
def solve(x, y=None):
    shared=set(); exclusive=None; value=y; live=True; out=[]
    for op,k,arg in x:
        if op=='shared':
            ok=live and k not in shared
            if ok: shared.add(k)
            out.append(ok)
        elif op=='exclusive':
            ok=live and not shared and exclusive is None
            if ok: exclusive=k
            out.append(ok)
        elif op=='release':
            shared.discard(k)
            if exclusive==k: exclusive=None
            out.append(True)
        elif op=='read':
            out.append(value if live and (k in shared or (exclusive is not None and k==exclusive)) else 'denied')
        elif op=='write':
            ok=live and exclusive is not None and k==exclusive
            if ok: value=arg
            out.append(ok)
        elif op=='ownerwrite':
            ok=live and not shared and exclusive is None
            if ok: value=arg
            out.append(ok)
        elif op=='move':
            ok=live and not shared and exclusive is None
            if ok: live=False
            out.append(ok)
        elif op=='inspect': out.append([value,live,sorted(shared),exclusive])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shared readers prohibit mutation', solve([['shared', 'a', None], ['shared', 'a', None], ['shared', 'b', None], ['exclusive', 'w', None], ['write', 'a', 'bad'], ['ownerwrite', None, 'bad'], ['move', None, None], ['read', 'a', None], ['read', 'ghost', None], ['inspect', None, None]], 'initial'), [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]])
check('exclusive token protects identity', solve([['exclusive', 'w', None], ['exclusive', 'other', None], ['shared', 'a', None], ['write', 'ghost', 'bad'], ['release', 'ghost', None], ['ownerwrite', None, 'bad'], ['move', None, None], ['write', 'w', 'new'], ['read', 'w', None], ['inspect', None, None]], 'initial'), [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']])
check('released token loses rights', solve([['shared', 'a', None], ['release', 'a', None], ['read', 'a', None], ['exclusive', 'w', None], ['release', 'w', None], ['write', 'w', 'bad'], ['ownerwrite', None, 'new'], ['inspect', None, None]], 'initial'), [True, True, 'denied', True, True, False, True, ['new', True, [], None]])
check('moved object stays unavailable', solve([['move', None, None], ['shared', 'a', None], ['exclusive', 'w', None], ['ownerwrite', None, 'bad'], ['read', None, None], ['move', None, None], ['inspect', None, None]], 'initial'), [True, False, False, False, 'denied', False, ['initial', False, [], None]])
check('None is not a borrowed token', solve([['read',None,None]], 'initial'), ['denied'])
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
shared readers prohibit mutation[True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]][True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]]Passed
exclusive token protects identity[True, False, True, False, True, False, False, True, 'new', ['new', True, ['a'], 'w']][True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']]Failed
released token loses rights[True, True, 'denied', True, True, False, True, ['new', True, [], None]][True, True, 'denied', True, True, False, True, ['new', True, [], None]]Passed
moved object stays unavailable[True, False, False, False, 'denied', False, ['initial', False, [], None]][True, False, False, False, 'denied', False, ['initial', False, [], None]]Passed
None is not a borrowed token['denied']['denied']Passed

SHA-256 / 4cadf3822a414c9214e3027a8e2a32e9f57e77e1f427d388aaae32ff54ff02ef

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x, y=None):
    shared=set(); exclusive=None; value=y; live=True; out=[]
    for op,k,arg in x:
        if op=='shared':
            ok=live and exclusive is None
            if ok: shared.add(k)
            out.append(ok)
        elif op=='exclusive':
            ok=live and not shared and exclusive is None
            if ok: exclusive=k
            out.append(ok)
        elif op=='release':
            shared.discard(k)
            if exclusive==k: exclusive=None
            out.append(True)
        elif op=='read':
            out.append(value if live and (k in shared or (exclusive is not None and k==exclusive)) else 'denied')
        elif op=='write':
            ok=live and exclusive is not None and k==exclusive
            if ok: value=arg
            out.append(ok)
        elif op=='ownerwrite':
            ok=live and not shared and exclusive is None
            if ok: value=arg
            out.append(ok)
        elif op=='move':
            ok=live and not shared and exclusive is None
            if ok: live=False
            out.append(ok)
        elif op=='inspect': out.append([value,live,sorted(shared),exclusive])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shared readers prohibit mutation', solve([['shared', 'a', None], ['shared', 'a', None], ['shared', 'b', None], ['exclusive', 'w', None], ['write', 'a', 'bad'], ['ownerwrite', None, 'bad'], ['move', None, None], ['read', 'a', None], ['read', 'ghost', None], ['inspect', None, None]], 'initial'), [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]])
check('exclusive token protects identity', solve([['exclusive', 'w', None], ['exclusive', 'other', None], ['shared', 'a', None], ['write', 'ghost', 'bad'], ['release', 'ghost', None], ['ownerwrite', None, 'bad'], ['move', None, None], ['write', 'w', 'new'], ['read', 'w', None], ['inspect', None, None]], 'initial'), [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']])
check('released token loses rights', solve([['shared', 'a', None], ['release', 'a', None], ['read', 'a', None], ['exclusive', 'w', None], ['release', 'w', None], ['write', 'w', 'bad'], ['ownerwrite', None, 'new'], ['inspect', None, None]], 'initial'), [True, True, 'denied', True, True, False, True, ['new', True, [], None]])
check('moved object stays unavailable', solve([['move', None, None], ['shared', 'a', None], ['exclusive', 'w', None], ['ownerwrite', None, 'bad'], ['read', None, None], ['move', None, None], ['inspect', None, None]], 'initial'), [True, False, False, False, 'denied', False, ['initial', False, [], None]])
check('None is not a borrowed token', solve([['read',None,None]], 'initial'), ['denied'])
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
shared readers prohibit mutation[True, True, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]][True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]]Failed
exclusive token protects identity[True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']][True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']]Passed
released token loses rights[True, True, 'denied', True, True, False, True, ['new', True, [], None]][True, True, 'denied', True, True, False, True, ['new', True, [], None]]Passed
moved object stays unavailable[True, False, False, False, 'denied', False, ['initial', False, [], None]][True, False, False, False, 'denied', False, ['initial', False, [], None]]Passed
None is not a borrowed token['denied']['denied']Passed

SHA-256 / c7f542b36f30d1f17e0eb55f72a0bf933ff67d5bab72cca04bcbdb6f3b54ec9a

3 / The verified repair

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

N = 1
observations = []
def solve(x, y=None):
    shared=set(); exclusive=None; value=y; live=True; out=[]
    for op,k,arg in x:
        if op=='shared':
            ok=live and exclusive is None and k not in shared
            if ok: shared.add(k)
            out.append(ok)
        elif op=='exclusive':
            ok=live and not shared and exclusive is None
            if ok: exclusive=k
            out.append(ok)
        elif op=='release':
            shared.discard(k)
            if exclusive==k: exclusive=None
            out.append(True)
        elif op=='read':
            out.append(value if live and (k in shared or (exclusive is not None and k==exclusive)) else 'denied')
        elif op=='write':
            ok=live and exclusive is not None and k==exclusive
            if ok: value=arg
            out.append(ok)
        elif op=='ownerwrite':
            ok=live and not shared and exclusive is None
            if ok: value=arg
            out.append(ok)
        elif op=='move':
            ok=live and not shared and exclusive is None
            if ok: live=False
            out.append(ok)
        elif op=='inspect': out.append([value,live,sorted(shared),exclusive])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shared readers prohibit mutation', solve([['shared', 'a', None], ['shared', 'a', None], ['shared', 'b', None], ['exclusive', 'w', None], ['write', 'a', 'bad'], ['ownerwrite', None, 'bad'], ['move', None, None], ['read', 'a', None], ['read', 'ghost', None], ['inspect', None, None]], 'initial'), [True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]])
check('exclusive token protects identity', solve([['exclusive', 'w', None], ['exclusive', 'other', None], ['shared', 'a', None], ['write', 'ghost', 'bad'], ['release', 'ghost', None], ['ownerwrite', None, 'bad'], ['move', None, None], ['write', 'w', 'new'], ['read', 'w', None], ['inspect', None, None]], 'initial'), [True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']])
check('released token loses rights', solve([['shared', 'a', None], ['release', 'a', None], ['read', 'a', None], ['exclusive', 'w', None], ['release', 'w', None], ['write', 'w', 'bad'], ['ownerwrite', None, 'new'], ['inspect', None, None]], 'initial'), [True, True, 'denied', True, True, False, True, ['new', True, [], None]])
check('moved object stays unavailable', solve([['move', None, None], ['shared', 'a', None], ['exclusive', 'w', None], ['ownerwrite', None, 'bad'], ['read', None, None], ['move', None, None], ['inspect', None, None]], 'initial'), [True, False, False, False, 'denied', False, ['initial', False, [], None]])
check('None is not a borrowed token', solve([['read',None,None]], 'initial'), ['denied'])
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
shared readers prohibit mutation[True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]][True, False, True, False, False, False, False, 'initial', 'denied', ['initial', True, ['a', 'b'], None]]Passed
exclusive token protects identity[True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']][True, False, False, False, True, False, False, True, 'new', ['new', True, [], 'w']]Passed
released token loses rights[True, True, 'denied', True, True, False, True, ['new', True, [], None]][True, True, 'denied', True, True, False, True, ['new', True, [], None]]Passed
moved object stays unavailable[True, False, False, False, 'denied', False, ['initial', False, [], None]][True, False, False, False, 'denied', False, ['initial', False, [], None]]Passed
None is not a borrowed token['denied']['denied']Passed

SHA-256 / 179e9bebac9713850918ef163042ca730821218a1f1f0f23d55cf7caa0466f20

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

Case digest / f6687f45e39f5341625c71a75819d9f81010fd2968620a8cad6d53be9c9b14d3