FAILURE MAP
← Case archive

FA-79416 / Barcode symbology encoding / Open access

Odd digit run enters set C without peeling a digit · case 01

A seven-digit run ends with a lone digit that forces another switch back to B.

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

ROOT CAUSE

The first digit of an odd run is not encoded in B before switching to C.

VERIFIED REPAIR

Encode one digit in B when the run length is odd, then switch.

Unsuccessful approach: Peeling a digit from even runs makes them odd inside set C.

Case contract

Plan Code 128 code sets for printable ASCII data (other characters -> None) as a list of [set, text] segments. Start in C when the data begins with at least 4 digits or is entirely digits of even length >= 2, else B. In C consume digit pairs and fall back to B when fewer than two digits remain in the run. In B switch to C before a run of at least 6 digits, or at least 4 digits that reach the end of the data; an odd run first encodes one digit in B. Empty data yields [["B", ""]].

Why this case matters

Retail, logistics, pharmacy and document workflows depend on encoders that produce exactly the module pattern, code-set switches, separators and quiet zones scanners expect; one misplaced module or separator makes a label unreadable or, worse, scan as different data.

1 / The failure

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

N = 1
observations = []
def solve(data):
    if any(not (32 <= ord(ch) <= 126) for ch in data):
        return None
    n = len(data)
    def run(j):
        k = j
        while k < n and data[k] in '0123456789':
            k += 1
        return k - j
    segs = []
    r = run(0)
    if r >= 4 or (r == n and n >= 2 and n % 2 == 0):
        cur = 'C'
    else:
        cur = 'B'
    buf = ''
    i = 0
    while i < n:
        if cur == 'C':
            if run(i) >= 2:
                buf += data[i:i + 2]
                i += 2
                continue
            segs.append(['C', buf])
            buf = ''
            cur = 'B'
            continue
        r = run(i)
        if r >= 6 or (r >= 4 and i + r == n):
            if False:
                buf += data[i]
                i += 1
            if buf:
                segs.append(['B', buf])
            buf = ''
            cur = 'C'
            continue
        buf += data[i]
        i += 1
    if buf or not segs:
        segs.append([cur, buf])
    return segs
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['Q7 2187698', [['B', 'Q7 2'], ['C', '187698']]], ['lot17764124x', [['B', 'lot'], ['C', '17764124'], ['B', 'x']]], ['ABlot61791', [['B', 'ABlot6'], ['C', '1791']]], ['3580131', [['C', '358013'], ['B', '1']]], ['xAB', [['B', 'xAB']]], ['AB', [['B', 'AB']]], ['x15', [['B', 'x15']]], ['Q7697394151338692706401453', [['B', 'Q7'], ['C', '697394151338692706401453']]]], [['-831943095', [['B', '-8'], ['C', '31943095']]], [' 1422146', [['B', ' 1'], ['C', '422146']]], ['Q7lotQ7lot', [['B', 'Q7lotQ7lot']]], ['101874486507729', [['C', '10187448650772'], ['B', '9']]], ['x22', [['B', 'x22']]], [' ', [['B', ' ']]], ['-006', [['B', '-006']]], ['lot13579626033845980', [['B', 'lot1'], ['C', '3579626033845980']]]], [[' 09255480AB663673713', [['B', ' '], ['C', '09255480'], ['B', 'AB6'], ['C', '63673713']]], ['x76654214lot2355', [['B', 'x'], ['C', '76654214'], ['B', 'lot'], ['C', '2355']]], [' 684915593AB', [['B', ' 6'], ['C', '84915593'], ['B', 'AB']]], ['0964853799773055547674lot', [['C', '0964853799773055547674'], ['B', 'lot']]], ['lot', [['B', 'lot']]], ['1', [['B', '1']]], ['Q7 lotAB', [['B', 'Q7 lotAB']]], ['827 AB51544', [['B', '827 AB5'], ['C', '1544']]]], [['lot1743-0346174', [['B', 'lot1743-0'], ['C', '346174']]], [' 705791-x', [['B', ' '], ['C', '705791'], ['B', '-x']]], ['lot6746309', [['B', 'lot6'], ['C', '746309']]], ['733-', [['B', '733-']]], ['46450162930', [['C', '4645016293'], ['B', '0']]], [' - ', [['B', ' - ']]], ['lot5899 ', [['B', 'lot5899 ']]], [' 838245148', [['B', ' 8'], ['C', '38245148']]]], [['10026xAB91695', [['C', '1002'], ['B', '6xAB9'], ['C', '1695']]], ['AB638804007 ', [['B', 'AB6'], ['C', '38804007'], ['B', ' ']]], ['AB98585', [['B', 'AB9'], ['C', '8585']]], ['AB8', [['B', 'AB8']]], ['014550632960 753', [['C', '014550632960'], ['B', ' 753']]], [' x', [['B', ' x']]], ['2637', [['C', '2637']]], ['lotx628901387', [['B', 'lotx6'], ['C', '28901387']]]]]
labels = ["regression: odd digit run alignment", "repair trap", "combined fault", "control", "control", "boundary", "boundary", "control"]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("%s %d" % (labels[i % len(labels)], i), 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
regression: odd digit run alignment 0[['B', 'Q7 '], ['C', '218769'], ['B', '8']][['B', 'Q7 2'], ['C', '187698']]Failed
repair trap 1[['B', 'lot'], ['C', '17764124'], ['B', 'x']][['B', 'lot'], ['C', '17764124'], ['B', 'x']]Passed
combined fault 2[['B', 'ABlot'], ['C', '6179'], ['B', '1']][['B', 'ABlot6'], ['C', '1791']]Failed
control 3[['C', '358013'], ['B', '1']][['C', '358013'], ['B', '1']]Passed
control 4[['B', 'xAB']][['B', 'xAB']]Passed
boundary 5[['B', 'AB']][['B', 'AB']]Passed
boundary 6[['B', 'x15']][['B', 'x15']]Passed
control 7[['B', 'Q'], ['C', '769739415133869270640145'], ['B', '3']][['B', 'Q7'], ['C', '697394151338692706401453']]Failed

SHA-256 / 510f4e048b199e052f96c084c1355767f3da38242a4518f2a469ba503016b370

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(data):
    if any(not (32 <= ord(ch) <= 126) for ch in data):
        return None
    n = len(data)
    def run(j):
        k = j
        while k < n and data[k] in '0123456789':
            k += 1
        return k - j
    segs = []
    r = run(0)
    if r >= 4 or (r == n and n >= 2 and n % 2 == 0):
        cur = 'C'
    else:
        cur = 'B'
    buf = ''
    i = 0
    while i < n:
        if cur == 'C':
            if run(i) >= 2:
                buf += data[i:i + 2]
                i += 2
                continue
            segs.append(['C', buf])
            buf = ''
            cur = 'B'
            continue
        r = run(i)
        if r >= 6 or (r >= 4 and i + r == n):
            if r % 2 == 0:
                buf += data[i]
                i += 1
            if buf:
                segs.append(['B', buf])
            buf = ''
            cur = 'C'
            continue
        buf += data[i]
        i += 1
    if buf or not segs:
        segs.append([cur, buf])
    return segs
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['Q7 2187698', [['B', 'Q7 2'], ['C', '187698']]], ['lot17764124x', [['B', 'lot'], ['C', '17764124'], ['B', 'x']]], ['ABlot61791', [['B', 'ABlot6'], ['C', '1791']]], ['3580131', [['C', '358013'], ['B', '1']]], ['xAB', [['B', 'xAB']]], ['AB', [['B', 'AB']]], ['x15', [['B', 'x15']]], ['Q7697394151338692706401453', [['B', 'Q7'], ['C', '697394151338692706401453']]]], [['-831943095', [['B', '-8'], ['C', '31943095']]], [' 1422146', [['B', ' 1'], ['C', '422146']]], ['Q7lotQ7lot', [['B', 'Q7lotQ7lot']]], ['101874486507729', [['C', '10187448650772'], ['B', '9']]], ['x22', [['B', 'x22']]], [' ', [['B', ' ']]], ['-006', [['B', '-006']]], ['lot13579626033845980', [['B', 'lot1'], ['C', '3579626033845980']]]], [[' 09255480AB663673713', [['B', ' '], ['C', '09255480'], ['B', 'AB6'], ['C', '63673713']]], ['x76654214lot2355', [['B', 'x'], ['C', '76654214'], ['B', 'lot'], ['C', '2355']]], [' 684915593AB', [['B', ' 6'], ['C', '84915593'], ['B', 'AB']]], ['0964853799773055547674lot', [['C', '0964853799773055547674'], ['B', 'lot']]], ['lot', [['B', 'lot']]], ['1', [['B', '1']]], ['Q7 lotAB', [['B', 'Q7 lotAB']]], ['827 AB51544', [['B', '827 AB5'], ['C', '1544']]]], [['lot1743-0346174', [['B', 'lot1743-0'], ['C', '346174']]], [' 705791-x', [['B', ' '], ['C', '705791'], ['B', '-x']]], ['lot6746309', [['B', 'lot6'], ['C', '746309']]], ['733-', [['B', '733-']]], ['46450162930', [['C', '4645016293'], ['B', '0']]], [' - ', [['B', ' - ']]], ['lot5899 ', [['B', 'lot5899 ']]], [' 838245148', [['B', ' 8'], ['C', '38245148']]]], [['10026xAB91695', [['C', '1002'], ['B', '6xAB9'], ['C', '1695']]], ['AB638804007 ', [['B', 'AB6'], ['C', '38804007'], ['B', ' ']]], ['AB98585', [['B', 'AB9'], ['C', '8585']]], ['AB8', [['B', 'AB8']]], ['014550632960 753', [['C', '014550632960'], ['B', ' 753']]], [' x', [['B', ' x']]], ['2637', [['C', '2637']]], ['lotx628901387', [['B', 'lotx6'], ['C', '28901387']]]]]
labels = ["regression: odd digit run alignment", "repair trap", "combined fault", "control", "control", "boundary", "boundary", "control"]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("%s %d" % (labels[i % len(labels)], i), 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
regression: odd digit run alignment 0[['B', 'Q7 '], ['C', '218769'], ['B', '8']][['B', 'Q7 2'], ['C', '187698']]Failed
repair trap 1[['B', 'lot1'], ['C', '776412'], ['B', '4x']][['B', 'lot'], ['C', '17764124'], ['B', 'x']]Failed
combined fault 2[['B', 'ABlot'], ['C', '6179'], ['B', '1']][['B', 'ABlot6'], ['C', '1791']]Failed
control 3[['C', '358013'], ['B', '1']][['C', '358013'], ['B', '1']]Passed
control 4[['B', 'xAB']][['B', 'xAB']]Passed
boundary 5[['B', 'AB']][['B', 'AB']]Passed
boundary 6[['B', 'x15']][['B', 'x15']]Passed
control 7[['B', 'Q'], ['C', '769739415133869270640145'], ['B', '3']][['B', 'Q7'], ['C', '697394151338692706401453']]Failed

SHA-256 / 6b3074d1bc9e5d3702815b3ce47f3047b2a6f670b72e97cba50841468169d400

3 / The verified repair

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

N = 1
observations = []
def solve(data):
    if any(not (32 <= ord(ch) <= 126) for ch in data):
        return None
    n = len(data)
    def run(j):
        k = j
        while k < n and data[k] in '0123456789':
            k += 1
        return k - j
    segs = []
    r = run(0)
    if r >= 4 or (r == n and n >= 2 and n % 2 == 0):
        cur = 'C'
    else:
        cur = 'B'
    buf = ''
    i = 0
    while i < n:
        if cur == 'C':
            if run(i) >= 2:
                buf += data[i:i + 2]
                i += 2
                continue
            segs.append(['C', buf])
            buf = ''
            cur = 'B'
            continue
        r = run(i)
        if r >= 6 or (r >= 4 and i + r == n):
            if r % 2 == 1:
                buf += data[i]
                i += 1
            if buf:
                segs.append(['B', buf])
            buf = ''
            cur = 'C'
            continue
        buf += data[i]
        i += 1
    if buf or not segs:
        segs.append([cur, buf])
    return segs
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['Q7 2187698', [['B', 'Q7 2'], ['C', '187698']]], ['lot17764124x', [['B', 'lot'], ['C', '17764124'], ['B', 'x']]], ['ABlot61791', [['B', 'ABlot6'], ['C', '1791']]], ['3580131', [['C', '358013'], ['B', '1']]], ['xAB', [['B', 'xAB']]], ['AB', [['B', 'AB']]], ['x15', [['B', 'x15']]], ['Q7697394151338692706401453', [['B', 'Q7'], ['C', '697394151338692706401453']]]], [['-831943095', [['B', '-8'], ['C', '31943095']]], [' 1422146', [['B', ' 1'], ['C', '422146']]], ['Q7lotQ7lot', [['B', 'Q7lotQ7lot']]], ['101874486507729', [['C', '10187448650772'], ['B', '9']]], ['x22', [['B', 'x22']]], [' ', [['B', ' ']]], ['-006', [['B', '-006']]], ['lot13579626033845980', [['B', 'lot1'], ['C', '3579626033845980']]]], [[' 09255480AB663673713', [['B', ' '], ['C', '09255480'], ['B', 'AB6'], ['C', '63673713']]], ['x76654214lot2355', [['B', 'x'], ['C', '76654214'], ['B', 'lot'], ['C', '2355']]], [' 684915593AB', [['B', ' 6'], ['C', '84915593'], ['B', 'AB']]], ['0964853799773055547674lot', [['C', '0964853799773055547674'], ['B', 'lot']]], ['lot', [['B', 'lot']]], ['1', [['B', '1']]], ['Q7 lotAB', [['B', 'Q7 lotAB']]], ['827 AB51544', [['B', '827 AB5'], ['C', '1544']]]], [['lot1743-0346174', [['B', 'lot1743-0'], ['C', '346174']]], [' 705791-x', [['B', ' '], ['C', '705791'], ['B', '-x']]], ['lot6746309', [['B', 'lot6'], ['C', '746309']]], ['733-', [['B', '733-']]], ['46450162930', [['C', '4645016293'], ['B', '0']]], [' - ', [['B', ' - ']]], ['lot5899 ', [['B', 'lot5899 ']]], [' 838245148', [['B', ' 8'], ['C', '38245148']]]], [['10026xAB91695', [['C', '1002'], ['B', '6xAB9'], ['C', '1695']]], ['AB638804007 ', [['B', 'AB6'], ['C', '38804007'], ['B', ' ']]], ['AB98585', [['B', 'AB9'], ['C', '8585']]], ['AB8', [['B', 'AB8']]], ['014550632960 753', [['C', '014550632960'], ['B', ' 753']]], [' x', [['B', ' x']]], ['2637', [['C', '2637']]], ['lotx628901387', [['B', 'lotx6'], ['C', '28901387']]]]]
labels = ["regression: odd digit run alignment", "repair trap", "combined fault", "control", "control", "boundary", "boundary", "control"]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("%s %d" % (labels[i % len(labels)], i), 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
regression: odd digit run alignment 0[['B', 'Q7 2'], ['C', '187698']][['B', 'Q7 2'], ['C', '187698']]Passed
repair trap 1[['B', 'lot'], ['C', '17764124'], ['B', 'x']][['B', 'lot'], ['C', '17764124'], ['B', 'x']]Passed
combined fault 2[['B', 'ABlot6'], ['C', '1791']][['B', 'ABlot6'], ['C', '1791']]Passed
control 3[['C', '358013'], ['B', '1']][['C', '358013'], ['B', '1']]Passed
control 4[['B', 'xAB']][['B', 'xAB']]Passed
boundary 5[['B', 'AB']][['B', 'AB']]Passed
boundary 6[['B', 'x15']][['B', 'x15']]Passed
control 7[['B', 'Q7'], ['C', '697394151338692706401453']][['B', 'Q7'], ['C', '697394151338692706401453']]Passed

SHA-256 / 1cbb1075f3d321d40dacfb5761313fbdfdf00d095e6da5a073d9d74255a00cfd

Verification & scope

A deterministic bounded teaching model with a stipulated contract; it makes no claim of conformance to any published specification. 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:44.392593+00:00.

Case digest / 35ccd70bb9d78473f87a30bcd62660b9670e1ea2ceeacdd9a204e52a9f4bea76