FAILURE MAP
← Case archive

FA-79731 / Barcode symbology encoding / Open access

EAN-2 add-on reuses the main symbol guard · case 01

Scanners do not detect the add-on because its start pattern is one module short.

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

ROOT CAUSE

The add-on starts with the three-module guard 101 instead of 1011.

VERIFIED REPAIR

Start the add-on with 1011.

Unsuccessful approach: Reversing the start pattern produces bar-bar-space-bar.

Case contract

Encode a two-digit EAN-2 add-on (issue number) as modules: start 1011, first character, separator 01, second character. The parity pattern is chosen by the two-digit value modulo 4: 0 LL, 1 LG, 2 GL, 3 GG, using the EAN L and G code sets. Invalid input returns None.

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(s):
    if len(s) != 2 or not all(c in '0123456789' for c in s):
        return None
    L = ['0001101', '0011001', '0010011', '0111101', '0100011', '0110001', '0101111', '0111011', '0110111', '0001011']
    G = ['0100111', '0110011', '0011011', '0100001', '0011101', '0111001', '0000101', '0010001', '0001001', '0010111']
    par = ['LL', 'LG', 'GL', 'GG'][int(s) % 4]
    a = (L if par[0] == 'L' else G)[int(s[0])]
    b = (L if par[1] == 'L' else G)[int(s[1])]
    return '101' + a + '01' + b
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['73', '10110111011010100001'], ['92', '10110001011010010011'], ['7', None], ['123', None], ['a1', None], ['55', '10110111001010111001'], ['27', '10110011011010010001'], ['42', '10110011101010010011']], [['24', '10110010011010100011'], ['29', '10110010011010010111'], ['123', None], ['a1', None], ['7', None], ['19', '10110110011010010111'], ['22', '10110011011010010011'], ['98', '10110010111010110111']], [['38', '10110100001010110111'], ['11', '10110110011010110011'], ['a1', None], ['7', None], ['123', None], ['17', '10110011001010010001'], ['64', '10110101111010100011'], ['01', '10110001101010110011']], [['66', '10110000101010101111'], ['51', '10110111001010110011'], ['7', None], ['123', None], ['a1', None], ['13', '10110011001010100001'], ['78', '10110010001010110111'], ['20', '10110010011010001101']], [['86', '10110001001010101111'], ['94', '10110010111010100011'], ['123', None], ['a1', None], ['7', None], ['81', '10110110111010110011'], ['29', '10110010011010010111'], ['30', '10110100001010001101']]]
labels = ["regression: add-on start pattern", "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 start pattern 0101011101101010000110110111011010100001Failed
repair trap 1101000101101001001110110001011010010011Failed
combined fault 2NoneNonePassed
control 3NoneNonePassed
control 4NoneNonePassed
boundary 5101011100101011100110110111001010111001Failed
boundary 6101001101101001000110110011011010010001Failed
control 7101001110101001001110110011101010010011Failed

SHA-256 / 34abf14f04bed6a3541eae3406ca5a4611956e6a08325cb30aa36e13b652377a

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(s):
    if len(s) != 2 or not all(c in '0123456789' for c in s):
        return None
    L = ['0001101', '0011001', '0010011', '0111101', '0100011', '0110001', '0101111', '0111011', '0110111', '0001011']
    G = ['0100111', '0110011', '0011011', '0100001', '0011101', '0111001', '0000101', '0010001', '0001001', '0010111']
    par = ['LL', 'LG', 'GL', 'GG'][int(s) % 4]
    a = (L if par[0] == 'L' else G)[int(s[0])]
    b = (L if par[1] == 'L' else G)[int(s[1])]
    return '1101' + a + '01' + b
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['73', '10110111011010100001'], ['92', '10110001011010010011'], ['7', None], ['123', None], ['a1', None], ['55', '10110111001010111001'], ['27', '10110011011010010001'], ['42', '10110011101010010011']], [['24', '10110010011010100011'], ['29', '10110010011010010111'], ['123', None], ['a1', None], ['7', None], ['19', '10110110011010010111'], ['22', '10110011011010010011'], ['98', '10110010111010110111']], [['38', '10110100001010110111'], ['11', '10110110011010110011'], ['a1', None], ['7', None], ['123', None], ['17', '10110011001010010001'], ['64', '10110101111010100011'], ['01', '10110001101010110011']], [['66', '10110000101010101111'], ['51', '10110111001010110011'], ['7', None], ['123', None], ['a1', None], ['13', '10110011001010100001'], ['78', '10110010001010110111'], ['20', '10110010011010001101']], [['86', '10110001001010101111'], ['94', '10110010111010100011'], ['123', None], ['a1', None], ['7', None], ['81', '10110110111010110011'], ['29', '10110010011010010111'], ['30', '10110100001010001101']]]
labels = ["regression: add-on start pattern", "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 start pattern 01101011101101010000110110111011010100001Failed
repair trap 11101000101101001001110110001011010010011Failed
combined fault 2NoneNonePassed
control 3NoneNonePassed
control 4NoneNonePassed
boundary 51101011100101011100110110111001010111001Failed
boundary 61101001101101001000110110011011010010001Failed
control 71101001110101001001110110011101010010011Failed

SHA-256 / a33e5996a522d8abb3fa47562ade94ffb6ccdae7183120be3f984d7ff41f5ed0

3 / The verified repair

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

N = 1
observations = []
def solve(s):
    if len(s) != 2 or not all(c in '0123456789' for c in s):
        return None
    L = ['0001101', '0011001', '0010011', '0111101', '0100011', '0110001', '0101111', '0111011', '0110111', '0001011']
    G = ['0100111', '0110011', '0011011', '0100001', '0011101', '0111001', '0000101', '0010001', '0001001', '0010111']
    par = ['LL', 'LG', 'GL', 'GG'][int(s) % 4]
    a = (L if par[0] == 'L' else G)[int(s[0])]
    b = (L if par[1] == 'L' else G)[int(s[1])]
    return '1011' + a + '01' + b
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['73', '10110111011010100001'], ['92', '10110001011010010011'], ['7', None], ['123', None], ['a1', None], ['55', '10110111001010111001'], ['27', '10110011011010010001'], ['42', '10110011101010010011']], [['24', '10110010011010100011'], ['29', '10110010011010010111'], ['123', None], ['a1', None], ['7', None], ['19', '10110110011010010111'], ['22', '10110011011010010011'], ['98', '10110010111010110111']], [['38', '10110100001010110111'], ['11', '10110110011010110011'], ['a1', None], ['7', None], ['123', None], ['17', '10110011001010010001'], ['64', '10110101111010100011'], ['01', '10110001101010110011']], [['66', '10110000101010101111'], ['51', '10110111001010110011'], ['7', None], ['123', None], ['a1', None], ['13', '10110011001010100001'], ['78', '10110010001010110111'], ['20', '10110010011010001101']], [['86', '10110001001010101111'], ['94', '10110010111010100011'], ['123', None], ['a1', None], ['7', None], ['81', '10110110111010110011'], ['29', '10110010011010010111'], ['30', '10110100001010001101']]]
labels = ["regression: add-on start pattern", "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 start pattern 01011011101101010000110110111011010100001Passed
repair trap 11011000101101001001110110001011010010011Passed
combined fault 2NoneNonePassed
control 3NoneNonePassed
control 4NoneNonePassed
boundary 51011011100101011100110110111001010111001Passed
boundary 61011001101101001000110110011011010010001Passed
control 71011001110101001001110110011101010010011Passed

SHA-256 / 44b5c83547b1b31a82f151736219a0a3f0ccae7b49b010414d3e40d281583693

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

Case digest / ceb02d46ef9d032ffb55e1540d838904eb18c71bf59db3cc062fabee9fd6e104