FAILURE MAP
← Case archive

FA-76181 / Chat ordering and read receipts / Open access

Choose which queued sends to dispatch now: dead does not block · case 01

Retry counts are looked up per conversation instead of per message, so a dead message is never recognised and blocks the queue forever.

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

ROOT CAUSE

The dead does not block decision evaluates `if failed.get(m['conv'], 0) >= 5:` where the contract requires `if failed.get(m['nonce'], 0) >= 5:`.

THE FAILURE

The dead does not block decision evaluates `if failed.get(m['conv'], 0) >= 5:` where the contract requires `if failed.get(m['nonce'], 0) >= 5:`.

Unsuccessful approach: Skipping dead messages only when they are due still lets a dead head with a future retry block the queue. The attempted `if failed.get(m['nonce'], 0) >= 5 and m['next_try'] <= now:` still disagrees with a fixture.

Case contract

outbox items {nonce, conv, order, next_try}. Per conversation, messages are sent strictly in numeric `order`: the head is the lowest-order message that is neither acknowledged nor dead (failed attempts >= 5). Dead messages are skipped without blocking. The head is dispatched when next_try <= now; later messages always wait for it. Result: nonces to dispatch, by conversation id then order.

Why this case matters

Outboxes must preserve per-conversation order across retries without letting a dead message block the queue.

1 / The failure

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

N = 1
observations = []
def solve(outbox, acked, failed, now):
    done = set(acked)
    out = []
    by_conv = {}
    for m in outbox:
        by_conv.setdefault(m['conv'], []).append(m)
    for conv in sorted(by_conv):
        for m in sorted(by_conv[conv], key=lambda m: m['order']):
            if m['nonce'] in done:
                continue
            if failed.get(m['conv'], 0) >= 5:
                continue
            if m['next_try'] <= now:
                out.append(m['nonce'])
            break
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
_CASES = {1: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 101}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 6}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 41}], [], {}, 41), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 1), ['p', 'q'])], 2: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 102}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 5}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 42}], [], {}, 42), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 2), ['p', 'q'])], 3: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 103}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 6}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 43}], [], {}, 43), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 3), ['p', 'q'])], 4: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 104}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 5}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 44}], [], {}, 44), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 4), ['p', 'q'])], 5: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 105}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 6}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 45}], [], {}, 45), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 5), ['p', 'q'])]}
for _label, _args, _expected in _CASES[N]:
    check(_label, solve(*_args), _expected)
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
head not yet due[][]Passed
dead head skipped[]['d2']Failed
due exactly now['e1']['e1']Passed
one tick early[][]Passed
acked head['g2']['g2']Passed
numeric order beyond nine['h9']['h9']Passed
two conversations['p', 'q']['p', 'q']Passed

SHA-256 / 9973b3e3f5a537d2ae2637bce0b94fc235d2f9093454a20b8f287669de1ab1c4

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(outbox, acked, failed, now):
    done = set(acked)
    out = []
    by_conv = {}
    for m in outbox:
        by_conv.setdefault(m['conv'], []).append(m)
    for conv in sorted(by_conv):
        for m in sorted(by_conv[conv], key=lambda m: m['order']):
            if m['nonce'] in done:
                continue
            if failed.get(m['nonce'], 0) >= 5 and m['next_try'] <= now:
                continue
            if m['next_try'] <= now:
                out.append(m['nonce'])
            break
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
_CASES = {1: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 101}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 6}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 41}], [], {}, 41), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 1), ['p', 'q'])], 2: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 102}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 5}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 42}], [], {}, 42), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 2), ['p', 'q'])], 3: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 103}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 6}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 43}], [], {}, 43), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 3), ['p', 'q'])], 4: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 104}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 5}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 44}], [], {}, 44), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 4), ['p', 'q'])], 5: [('head not yet due', ([{'nonce': 'a1', 'conv': 'c', 'order': 1, 'next_try': 105}, {'nonce': 'a2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {}, 50), []), ('dead head skipped', ([{'nonce': 'd1', 'conv': 'c', 'order': 1, 'next_try': 999}, {'nonce': 'd2', 'conv': 'c', 'order': 2, 'next_try': 0}], [], {'d1': 6}, 10), ['d2']), ('due exactly now', ([{'nonce': 'e1', 'conv': 'k', 'order': 3, 'next_try': 45}], [], {}, 45), ['e1']), ('one tick early', ([{'nonce': 'f1', 'conv': 'k', 'order': 1, 'next_try': 41}], [], {}, 40), []), ('acked head', ([{'nonce': 'g1', 'conv': 'c', 'order': 2, 'next_try': 0}, {'nonce': 'g2', 'conv': 'c', 'order': 3, 'next_try': 0}], ['g1'], {}, 5), ['g2']), ('numeric order beyond nine', ([{'nonce': 'h10', 'conv': 'z', 'order': 10, 'next_try': 0}, {'nonce': 'h9', 'conv': 'z', 'order': 9, 'next_try': 0}], [], {}, 1), ['h9']), ('two conversations', ([{'nonce': 'q', 'conv': 'b', 'order': 1, 'next_try': 0}, {'nonce': 'p', 'conv': 'a', 'order': 1, 'next_try': 0}, {'nonce': 'r', 'conv': 'a', 'order': 2, 'next_try': 0}], [], {}, 5), ['p', 'q'])]}
for _label, _args, _expected in _CASES[N]:
    check(_label, solve(*_args), _expected)
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
head not yet due[][]Passed
dead head skipped[]['d2']Failed
due exactly now['e1']['e1']Passed
one tick early[][]Passed
acked head['g2']['g2']Passed
numeric order beyond nine['h9']['h9']Passed
two conversations['p', 'q']['p', 'q']Passed

SHA-256 / c34ce3a7b206f676420987006e42f2df806c42faceb969f53637ac8a99ea208e

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 7 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

Verification & scope

Stipulated offline chat model; not a complete messaging protocol, client or server implementation. 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:49:14.051003+00:00.

Case digest / 8386694ca14010323355c72766d684912fff0bfc4c0e587004783da2c7ef7aec