FAILURE MAP
← Case archive

FA-79506 / Barcode symbology encoding / Open access

Add-ons are allowed on Code 128 · case 01

Layouts reserve space for an EAN-5 next to a Code 128 symbol that scanners will never read together.

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

ROOT CAUSE

The add-on is not restricted to EAN/UPC symbologies.

VERIFIED REPAIR

Allow add-ons only on EAN-13, UPC-A and EAN-8.

Unsuccessful approach: Excluding only Code 39 still admits Code 128 and ITF-14.

Case contract

Input {sym, modules, x_um, addon?}. Quiet zones in X: ean13 11 left / 7 right, upca 9/9, ean8 7/7, code128, code39 and itf14 10/10. Allowed X-dimensions in micrometres: EAN/UPC 264..660 inclusive, code128/code39 >= 190, itf14 >= 495. An EAN-2 (20 modules) or EAN-5 (47 modules) add-on is only allowed on EAN/UPC; it replaces the right quiet zone by a 7-module gap, the add-on and a 5-module trailing quiet zone. Return [total_um, left_quiet_um] or unknown/x-out-of-range/bad-addon.

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(spec):
    qz = {'ean13': (11, 7), 'upca': (9, 9), 'ean8': (7, 7), 'code128': (10, 10), 'code39': (10, 10), 'itf14': (10, 10)}
    xr = {'ean13': (264, 660), 'upca': (264, 660), 'ean8': (264, 660), 'code128': (190, None), 'code39': (190, None), 'itf14': (495, None)}
    sym = spec['sym']
    if sym not in qz:
        return 'unknown'
    lo, hi = xr[sym]
    x = spec['x_um']
    if x < lo or (hi is not None and x > hi):
        return 'x-out-of-range'
    left, right = qz[sym]
    addon = spec.get('addon', 0)
    if addon:
        if addon not in (2, 5):
            return 'bad-addon'
        right = 7 + (20 if addon == 2 else 47) + 5
    total = left + spec['modules'] + right
    return [total * x, left * x]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[{'sym': 'code128', 'modules': 200, 'x_um': 1000, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 200, 'x_um': 495, 'addon': 2}, 'bad-addon'], [{'sym': 'code39', 'modules': 200, 'x_um': 661}, [145420, 6610]], [{'sym': 'ean13', 'modules': 67, 'x_um': 330}, [28050, 3630]], [{'sym': 'qr', 'modules': 200, 'x_um': 250, 'addon': 2}, 'unknown'], [{'sym': 'ean8', 'modules': 101, 'x_um': 1100, 'addon': 5}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 95, 'x_um': 250, 'addon': 2}, 'x-out-of-range'], [{'sym': 'code128', 'modules': 67, 'x_um': 400, 'addon': 2}, 'bad-addon']], [[{'sym': 'code39', 'modules': 95, 'x_um': 661, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 263, 'addon': 5}, 'bad-addon'], [{'sym': 'itf14', 'modules': 142, 'x_um': 495, 'addon': 2}, 'bad-addon'], [{'sym': 'itf14', 'modules': 67, 'x_um': 1000}, [87000, 10000]], [{'sym': 'itf14', 'modules': 67, 'x_um': 250}, 'x-out-of-range'], [{'sym': 'code128', 'modules': 200, 'x_um': 660}, [145200, 6600]], [{'sym': 'ean13', 'modules': 95, 'x_um': 661}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 67, 'x_um': 330, 'addon': 5}, 'bad-addon']], [[{'sym': 'code39', 'modules': 200, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'itf14', 'modules': 200, 'x_um': 1100, 'addon': 2}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 661, 'addon': 5}, 'bad-addon'], [{'sym': 'ean13', 'modules': 200, 'x_um': 190}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 101, 'x_um': 400}, [48400, 4000]], [{'sym': 'itf14', 'modules': 95, 'x_um': 263, 'addon': 5}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 101, 'x_um': 190, 'addon': 3}, 'bad-addon'], [{'sym': 'code39', 'modules': 101, 'x_um': 660, 'addon': 2}, 'bad-addon']], [[{'sym': 'code128', 'modules': 101, 'x_um': 400, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 250, 'addon': 2}, 'bad-addon'], [{'sym': 'ean8', 'modules': 142, 'x_um': 400, 'addon': 5}, [83200, 2800]], [{'sym': 'ean13', 'modules': 101, 'x_um': 1100}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 95, 'x_um': 264, 'addon': 2}, 'x-out-of-range'], [{'sym': 'ean13', 'modules': 67, 'x_um': 661}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 67, 'x_um': 1100, 'addon': 3}, 'bad-addon'], [{'sym': 'code39', 'modules': 142, 'x_um': 263, 'addon': 5}, 'bad-addon']], [[{'sym': 'code39', 'modules': 142, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 101, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 250, 'addon': 2}, 'bad-addon'], [{'sym': 'ean13', 'modules': 67, 'x_um': 330}, [28050, 3630]], [{'sym': 'ean13', 'modules': 101, 'x_um': 264}, [31416, 2904]], [{'sym': 'ean13', 'modules': 67, 'x_um': 264, 'addon': 2}, [29040, 2904]], [{'sym': 'code128', 'modules': 101, 'x_um': 400}, [48400, 4000]], [{'sym': 'itf14', 'modules': 200, 'x_um': 661, 'addon': 5}, 'bad-addon']]]
labels = ["regression: add-on symbology restriction", "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: add-on symbology restriction 0[269000, 10000]bad-addonFailed
repair trap 1[119790, 4950]bad-addonFailed
combined fault 2[145420, 6610][145420, 6610]Passed
control 3[28050, 3630][28050, 3630]Passed
control 4unknownunknownPassed
boundary 5x-out-of-rangex-out-of-rangePassed
boundary 6x-out-of-rangex-out-of-rangePassed
control 7[43600, 4000]bad-addonFailed

SHA-256 / c6a4bf17aeda10fea670ea4a56fa828cbf88b2faf8822df703ba1adb215137b9

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(spec):
    qz = {'ean13': (11, 7), 'upca': (9, 9), 'ean8': (7, 7), 'code128': (10, 10), 'code39': (10, 10), 'itf14': (10, 10)}
    xr = {'ean13': (264, 660), 'upca': (264, 660), 'ean8': (264, 660), 'code128': (190, None), 'code39': (190, None), 'itf14': (495, None)}
    sym = spec['sym']
    if sym not in qz:
        return 'unknown'
    lo, hi = xr[sym]
    x = spec['x_um']
    if x < lo or (hi is not None and x > hi):
        return 'x-out-of-range'
    left, right = qz[sym]
    addon = spec.get('addon', 0)
    if addon:
        if sym == 'code39' or addon not in (2, 5):
            return 'bad-addon'
        right = 7 + (20 if addon == 2 else 47) + 5
    total = left + spec['modules'] + right
    return [total * x, left * x]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[{'sym': 'code128', 'modules': 200, 'x_um': 1000, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 200, 'x_um': 495, 'addon': 2}, 'bad-addon'], [{'sym': 'code39', 'modules': 200, 'x_um': 661}, [145420, 6610]], [{'sym': 'ean13', 'modules': 67, 'x_um': 330}, [28050, 3630]], [{'sym': 'qr', 'modules': 200, 'x_um': 250, 'addon': 2}, 'unknown'], [{'sym': 'ean8', 'modules': 101, 'x_um': 1100, 'addon': 5}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 95, 'x_um': 250, 'addon': 2}, 'x-out-of-range'], [{'sym': 'code128', 'modules': 67, 'x_um': 400, 'addon': 2}, 'bad-addon']], [[{'sym': 'code39', 'modules': 95, 'x_um': 661, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 263, 'addon': 5}, 'bad-addon'], [{'sym': 'itf14', 'modules': 142, 'x_um': 495, 'addon': 2}, 'bad-addon'], [{'sym': 'itf14', 'modules': 67, 'x_um': 1000}, [87000, 10000]], [{'sym': 'itf14', 'modules': 67, 'x_um': 250}, 'x-out-of-range'], [{'sym': 'code128', 'modules': 200, 'x_um': 660}, [145200, 6600]], [{'sym': 'ean13', 'modules': 95, 'x_um': 661}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 67, 'x_um': 330, 'addon': 5}, 'bad-addon']], [[{'sym': 'code39', 'modules': 200, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'itf14', 'modules': 200, 'x_um': 1100, 'addon': 2}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 661, 'addon': 5}, 'bad-addon'], [{'sym': 'ean13', 'modules': 200, 'x_um': 190}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 101, 'x_um': 400}, [48400, 4000]], [{'sym': 'itf14', 'modules': 95, 'x_um': 263, 'addon': 5}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 101, 'x_um': 190, 'addon': 3}, 'bad-addon'], [{'sym': 'code39', 'modules': 101, 'x_um': 660, 'addon': 2}, 'bad-addon']], [[{'sym': 'code128', 'modules': 101, 'x_um': 400, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 250, 'addon': 2}, 'bad-addon'], [{'sym': 'ean8', 'modules': 142, 'x_um': 400, 'addon': 5}, [83200, 2800]], [{'sym': 'ean13', 'modules': 101, 'x_um': 1100}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 95, 'x_um': 264, 'addon': 2}, 'x-out-of-range'], [{'sym': 'ean13', 'modules': 67, 'x_um': 661}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 67, 'x_um': 1100, 'addon': 3}, 'bad-addon'], [{'sym': 'code39', 'modules': 142, 'x_um': 263, 'addon': 5}, 'bad-addon']], [[{'sym': 'code39', 'modules': 142, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 101, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 250, 'addon': 2}, 'bad-addon'], [{'sym': 'ean13', 'modules': 67, 'x_um': 330}, [28050, 3630]], [{'sym': 'ean13', 'modules': 101, 'x_um': 264}, [31416, 2904]], [{'sym': 'ean13', 'modules': 67, 'x_um': 264, 'addon': 2}, [29040, 2904]], [{'sym': 'code128', 'modules': 101, 'x_um': 400}, [48400, 4000]], [{'sym': 'itf14', 'modules': 200, 'x_um': 661, 'addon': 5}, 'bad-addon']]]
labels = ["regression: add-on symbology restriction", "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: add-on symbology restriction 0[269000, 10000]bad-addonFailed
repair trap 1[119790, 4950]bad-addonFailed
combined fault 2[145420, 6610][145420, 6610]Passed
control 3[28050, 3630][28050, 3630]Passed
control 4unknownunknownPassed
boundary 5x-out-of-rangex-out-of-rangePassed
boundary 6x-out-of-rangex-out-of-rangePassed
control 7[43600, 4000]bad-addonFailed

SHA-256 / 86aee82131a52bb2c65215446f647339f3e6d7b22f47bd53fb833956d4ead964

3 / The verified repair

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

N = 1
observations = []
def solve(spec):
    qz = {'ean13': (11, 7), 'upca': (9, 9), 'ean8': (7, 7), 'code128': (10, 10), 'code39': (10, 10), 'itf14': (10, 10)}
    xr = {'ean13': (264, 660), 'upca': (264, 660), 'ean8': (264, 660), 'code128': (190, None), 'code39': (190, None), 'itf14': (495, None)}
    sym = spec['sym']
    if sym not in qz:
        return 'unknown'
    lo, hi = xr[sym]
    x = spec['x_um']
    if x < lo or (hi is not None and x > hi):
        return 'x-out-of-range'
    left, right = qz[sym]
    addon = spec.get('addon', 0)
    if addon:
        if sym not in ('ean13', 'upca', 'ean8') or addon not in (2, 5):
            return 'bad-addon'
        right = 7 + (20 if addon == 2 else 47) + 5
    total = left + spec['modules'] + right
    return [total * x, left * x]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[{'sym': 'code128', 'modules': 200, 'x_um': 1000, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 200, 'x_um': 495, 'addon': 2}, 'bad-addon'], [{'sym': 'code39', 'modules': 200, 'x_um': 661}, [145420, 6610]], [{'sym': 'ean13', 'modules': 67, 'x_um': 330}, [28050, 3630]], [{'sym': 'qr', 'modules': 200, 'x_um': 250, 'addon': 2}, 'unknown'], [{'sym': 'ean8', 'modules': 101, 'x_um': 1100, 'addon': 5}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 95, 'x_um': 250, 'addon': 2}, 'x-out-of-range'], [{'sym': 'code128', 'modules': 67, 'x_um': 400, 'addon': 2}, 'bad-addon']], [[{'sym': 'code39', 'modules': 95, 'x_um': 661, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 263, 'addon': 5}, 'bad-addon'], [{'sym': 'itf14', 'modules': 142, 'x_um': 495, 'addon': 2}, 'bad-addon'], [{'sym': 'itf14', 'modules': 67, 'x_um': 1000}, [87000, 10000]], [{'sym': 'itf14', 'modules': 67, 'x_um': 250}, 'x-out-of-range'], [{'sym': 'code128', 'modules': 200, 'x_um': 660}, [145200, 6600]], [{'sym': 'ean13', 'modules': 95, 'x_um': 661}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 67, 'x_um': 330, 'addon': 5}, 'bad-addon']], [[{'sym': 'code39', 'modules': 200, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'itf14', 'modules': 200, 'x_um': 1100, 'addon': 2}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 661, 'addon': 5}, 'bad-addon'], [{'sym': 'ean13', 'modules': 200, 'x_um': 190}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 101, 'x_um': 400}, [48400, 4000]], [{'sym': 'itf14', 'modules': 95, 'x_um': 263, 'addon': 5}, 'x-out-of-range'], [{'sym': 'code39', 'modules': 101, 'x_um': 190, 'addon': 3}, 'bad-addon'], [{'sym': 'code39', 'modules': 101, 'x_um': 660, 'addon': 2}, 'bad-addon']], [[{'sym': 'code128', 'modules': 101, 'x_um': 400, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 250, 'addon': 2}, 'bad-addon'], [{'sym': 'ean8', 'modules': 142, 'x_um': 400, 'addon': 5}, [83200, 2800]], [{'sym': 'ean13', 'modules': 101, 'x_um': 1100}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 95, 'x_um': 264, 'addon': 2}, 'x-out-of-range'], [{'sym': 'ean13', 'modules': 67, 'x_um': 661}, 'x-out-of-range'], [{'sym': 'itf14', 'modules': 67, 'x_um': 1100, 'addon': 3}, 'bad-addon'], [{'sym': 'code39', 'modules': 142, 'x_um': 263, 'addon': 5}, 'bad-addon']], [[{'sym': 'code39', 'modules': 142, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 101, 'x_um': 190, 'addon': 5}, 'bad-addon'], [{'sym': 'code128', 'modules': 67, 'x_um': 250, 'addon': 2}, 'bad-addon'], [{'sym': 'ean13', 'modules': 67, 'x_um': 330}, [28050, 3630]], [{'sym': 'ean13', 'modules': 101, 'x_um': 264}, [31416, 2904]], [{'sym': 'ean13', 'modules': 67, 'x_um': 264, 'addon': 2}, [29040, 2904]], [{'sym': 'code128', 'modules': 101, 'x_um': 400}, [48400, 4000]], [{'sym': 'itf14', 'modules': 200, 'x_um': 661, 'addon': 5}, 'bad-addon']]]
labels = ["regression: add-on symbology restriction", "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: add-on symbology restriction 0bad-addonbad-addonPassed
repair trap 1bad-addonbad-addonPassed
combined fault 2[145420, 6610][145420, 6610]Passed
control 3[28050, 3630][28050, 3630]Passed
control 4unknownunknownPassed
boundary 5x-out-of-rangex-out-of-rangePassed
boundary 6x-out-of-rangex-out-of-rangePassed
control 7bad-addonbad-addonPassed

SHA-256 / 8d3f33e973962cb5490cd4cd2aa7aac4f0793f59e263a2a468b3f1f4dd227fba

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

Case digest / ad111081573944a6adf1b38211919eed73f163b8be32a23a09b1c959c4dafcc8