FAILURE MAP
← Case archive

FA-79451 / Barcode symbology encoding / Open access

Leading FNC1 is emitted without a start character · case 01

GS1 symbols begin with value 102 and no start code, so scanners reject them.

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

ROOT CAUSE

A FNC1 before any set segment silently assumes set B without emitting its start.

VERIFIED REPAIR

Report no-start when FNC1 appears before any set segment.

Unsuccessful approach: Emitting a start C without recording the current set duplicates the start on the next segment.

Case contract

Turn planned Code 128 segments into symbol values (without the checksum). Segments are [set, text], ["FNC1"] or ["SHIFT", char]. The first set segment emits its start (A 103, B 104, C 105); later set changes emit Code A 101, Code B 100 or Code C 99. Set A encodes 32..95 as ord-32 and 0..31 as ord+64; set B encodes 32..127 as ord-32; set C encodes even-length ASCII digit text as pair values. FNC1 is 102 and needs a prior start; SHIFT (98) is only valid in A or B and encodes one character in the other of A/B. Errors: no-start, bad-shift, bad-c, unencodable.

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(segs):
    out = []
    cur = None
    starts = {'A': 103, 'B': 104, 'C': 105}
    switch = {'A': 101, 'B': 100, 'C': 99}
    def val(s, ch):
        o = ord(ch)
        if s == 'A':
            if 32 <= o <= 95:
                return o - 32
            if 0 <= o <= 31:
                return o + 64
            return None
        if 32 <= o <= 127:
            return o - 32
        return None
    for seg in segs:
        kind = seg[0]
        if kind == 'FNC1':
            if cur is None:
                cur = 'B'
            out.append(102)
            continue
        if kind == 'SHIFT':
            if cur not in ('A', 'B'):
                return {'error': 'bad-shift'}
            other = 'B' if cur == 'A' else 'A'
            v = val(other, seg[1])
            if v is None:
                return {'error': 'unencodable', 'char': seg[1]}
            out += [98, v]
            continue
        s, text = seg
        if cur is None:
            out.append(starts[s])
        elif s != cur:
            out.append(switch[s])
        cur = s
        if s == 'C':
            if len(text) % 2 or not all(c in '0123456789' for c in text):
                return {'error': 'bad-c'}
            out += [int(text[j:j + 2]) for j in range(0, len(text), 2)]
        else:
            for ch in text:
                v = val(s, ch)
                if v is None:
                    return {'error': 'unencodable', 'char': ch}
                out.append(v)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['FNC1'], ['B', 'Lot 7'], ['A', '\x00Q']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'z'], ['C', '123']], {'error': 'no-start'}], [[['C', '12'], ['A', 'HELLO']], [105, 12, 101, 40, 37, 44, 44, 47]], [[['B', 'Q'], ['B', '{x}'], ['C', '123']], {'error': 'bad-c'}], [[['B', '{x}'], ['SHIFT', '\t'], ['C', '1'], ['A', '\x00Q']], {'error': 'bad-c'}], [[['B', 'ab'], ['A', '\x00Q'], ['SHIFT', '\t'], ['FNC1']], {'error': 'unencodable', 'char': '\t'}], [[['C', '123'], ['FNC1']], {'error': 'bad-c'}], [[['FNC1'], ['A', '\t']], {'error': 'no-start'}]], [[[['FNC1'], ['B', 'z~'], ['B', 'Q'], ['FNC1'], ['A', '\x00Q']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'a']], {'error': 'no-start'}], [[['C', '1'], ['C', '12']], {'error': 'bad-c'}], [[['A', '\x00Q'], ['B', '{x}'], ['A', 'X\x1d1'], ['SHIFT', 'z']], [103, 64, 49, 100, 91, 88, 93, 101, 56, 93, 17, 98, 90]], [[['A', 'AB'], ['B', 'Q'], ['B', 'z~']], [103, 33, 34, 100, 49, 90, 94]], [[['A', 'AB'], ['FNC1']], [103, 33, 34, 102]], [[['B', 'z~'], ['SHIFT', 'z'], ['FNC1']], {'error': 'unencodable', 'char': 'z'}], [[['FNC1'], ['B', 'Lot 7']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', 'a'], ['C', '1'], ['FNC1']], {'error': 'no-start'}], [[['FNC1'], ['B', 'z~']], {'error': 'no-start'}], [[['B', 'Lot 7']], [104, 44, 79, 84, 0, 23]], [[['C', '0099']], [105, 0, 99]], [[['A', 'AB']], [103, 33, 34]], [[['A', 'X\x1d1']], [103, 56, 93, 17]], [[['C', '12']], [105, 12]], [[['FNC1'], ['FNC1'], ['A', 'HELLO'], ['C', '4711']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', 'z'], ['FNC1']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'B']], {'error': 'no-start'}], [[['B', 'Lot 7'], ['C', ' 1'], ['A', 'AB'], ['B', 'ab']], {'error': 'bad-c'}], [[['C', '4711'], ['B', 'ab'], ['A', 'X\x1d1']], [105, 47, 11, 100, 65, 66, 101, 56, 93, 17]], [[['B', 'z~']], [104, 90, 94]], [[['C', ' 1'], ['FNC1'], ['C', ' 1'], ['A', '_^']], {'error': 'bad-c'}], [[['C', ' 1'], ['C', '0099']], {'error': 'bad-c'}], [[['FNC1'], ['A', '\t'], ['A', 'A`']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', '\x1d'], ['B', 'z~'], ['A', 'AB']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', '\x1d']], {'error': 'no-start'}], [[['B', 'Q']], [104, 49]], [[['A', '\t'], ['C', '0099']], [103, 73, 99, 0, 99]], [[['C', '4711'], ['B', 'Q'], ['B', '{x}']], [105, 47, 11, 100, 49, 91, 88, 93]], [[['B', '{x}'], ['B', 'Q']], [104, 91, 88, 93, 49]], [[['A', 'AB']], [103, 33, 34]], [[['FNC1'], ['A', 'X\x1d1']], {'error': 'no-start'}]]]
labels = ["regression: FNC1 before a start character", "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: FNC1 before a start character 0[102, 44, 79, 84, 0, 23, 101, 64, 49]{'error': 'no-start'}Failed
repair trap 1{'char': 'z', 'error': 'unencodable'}{'error': 'no-start'}Failed
combined fault 2[105, 12, 101, 40, 37, 44, 44, 47][105, 12, 101, 40, 37, 44, 44, 47]Passed
control 3{'error': 'bad-c'}{'error': 'bad-c'}Passed
control 4{'error': 'bad-c'}{'error': 'bad-c'}Passed
boundary 5{'char': '\t', 'error': 'unencodable'}{'char': '\t', 'error': 'unencodable'}Passed
boundary 6{'error': 'bad-c'}{'error': 'bad-c'}Passed
control 7[102, 101, 73]{'error': 'no-start'}Failed

SHA-256 / 26b23c9c3387a7061b10f85d71ba81ab92660654c3a5c88feb34d927b2d3c5eb

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(segs):
    out = []
    cur = None
    starts = {'A': 103, 'B': 104, 'C': 105}
    switch = {'A': 101, 'B': 100, 'C': 99}
    def val(s, ch):
        o = ord(ch)
        if s == 'A':
            if 32 <= o <= 95:
                return o - 32
            if 0 <= o <= 31:
                return o + 64
            return None
        if 32 <= o <= 127:
            return o - 32
        return None
    for seg in segs:
        kind = seg[0]
        if kind == 'FNC1':
            if cur is None:
                out.append(105)
            out.append(102)
            continue
        if kind == 'SHIFT':
            if cur not in ('A', 'B'):
                return {'error': 'bad-shift'}
            other = 'B' if cur == 'A' else 'A'
            v = val(other, seg[1])
            if v is None:
                return {'error': 'unencodable', 'char': seg[1]}
            out += [98, v]
            continue
        s, text = seg
        if cur is None:
            out.append(starts[s])
        elif s != cur:
            out.append(switch[s])
        cur = s
        if s == 'C':
            if len(text) % 2 or not all(c in '0123456789' for c in text):
                return {'error': 'bad-c'}
            out += [int(text[j:j + 2]) for j in range(0, len(text), 2)]
        else:
            for ch in text:
                v = val(s, ch)
                if v is None:
                    return {'error': 'unencodable', 'char': ch}
                out.append(v)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['FNC1'], ['B', 'Lot 7'], ['A', '\x00Q']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'z'], ['C', '123']], {'error': 'no-start'}], [[['C', '12'], ['A', 'HELLO']], [105, 12, 101, 40, 37, 44, 44, 47]], [[['B', 'Q'], ['B', '{x}'], ['C', '123']], {'error': 'bad-c'}], [[['B', '{x}'], ['SHIFT', '\t'], ['C', '1'], ['A', '\x00Q']], {'error': 'bad-c'}], [[['B', 'ab'], ['A', '\x00Q'], ['SHIFT', '\t'], ['FNC1']], {'error': 'unencodable', 'char': '\t'}], [[['C', '123'], ['FNC1']], {'error': 'bad-c'}], [[['FNC1'], ['A', '\t']], {'error': 'no-start'}]], [[[['FNC1'], ['B', 'z~'], ['B', 'Q'], ['FNC1'], ['A', '\x00Q']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'a']], {'error': 'no-start'}], [[['C', '1'], ['C', '12']], {'error': 'bad-c'}], [[['A', '\x00Q'], ['B', '{x}'], ['A', 'X\x1d1'], ['SHIFT', 'z']], [103, 64, 49, 100, 91, 88, 93, 101, 56, 93, 17, 98, 90]], [[['A', 'AB'], ['B', 'Q'], ['B', 'z~']], [103, 33, 34, 100, 49, 90, 94]], [[['A', 'AB'], ['FNC1']], [103, 33, 34, 102]], [[['B', 'z~'], ['SHIFT', 'z'], ['FNC1']], {'error': 'unencodable', 'char': 'z'}], [[['FNC1'], ['B', 'Lot 7']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', 'a'], ['C', '1'], ['FNC1']], {'error': 'no-start'}], [[['FNC1'], ['B', 'z~']], {'error': 'no-start'}], [[['B', 'Lot 7']], [104, 44, 79, 84, 0, 23]], [[['C', '0099']], [105, 0, 99]], [[['A', 'AB']], [103, 33, 34]], [[['A', 'X\x1d1']], [103, 56, 93, 17]], [[['C', '12']], [105, 12]], [[['FNC1'], ['FNC1'], ['A', 'HELLO'], ['C', '4711']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', 'z'], ['FNC1']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'B']], {'error': 'no-start'}], [[['B', 'Lot 7'], ['C', ' 1'], ['A', 'AB'], ['B', 'ab']], {'error': 'bad-c'}], [[['C', '4711'], ['B', 'ab'], ['A', 'X\x1d1']], [105, 47, 11, 100, 65, 66, 101, 56, 93, 17]], [[['B', 'z~']], [104, 90, 94]], [[['C', ' 1'], ['FNC1'], ['C', ' 1'], ['A', '_^']], {'error': 'bad-c'}], [[['C', ' 1'], ['C', '0099']], {'error': 'bad-c'}], [[['FNC1'], ['A', '\t'], ['A', 'A`']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', '\x1d'], ['B', 'z~'], ['A', 'AB']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', '\x1d']], {'error': 'no-start'}], [[['B', 'Q']], [104, 49]], [[['A', '\t'], ['C', '0099']], [103, 73, 99, 0, 99]], [[['C', '4711'], ['B', 'Q'], ['B', '{x}']], [105, 47, 11, 100, 49, 91, 88, 93]], [[['B', '{x}'], ['B', 'Q']], [104, 91, 88, 93, 49]], [[['A', 'AB']], [103, 33, 34]], [[['FNC1'], ['A', 'X\x1d1']], {'error': 'no-start'}]]]
labels = ["regression: FNC1 before a start character", "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: FNC1 before a start character 0[105, 102, 104, 44, 79, 84, 0, 23, 101, 64, 49]{'error': 'no-start'}Failed
repair trap 1{'error': 'bad-shift'}{'error': 'no-start'}Failed
combined fault 2[105, 12, 101, 40, 37, 44, 44, 47][105, 12, 101, 40, 37, 44, 44, 47]Passed
control 3{'error': 'bad-c'}{'error': 'bad-c'}Passed
control 4{'error': 'bad-c'}{'error': 'bad-c'}Passed
boundary 5{'char': '\t', 'error': 'unencodable'}{'char': '\t', 'error': 'unencodable'}Passed
boundary 6{'error': 'bad-c'}{'error': 'bad-c'}Passed
control 7[105, 102, 103, 73]{'error': 'no-start'}Failed

SHA-256 / 226b1973f1a15de002599ed666c1c57c07a016e23da440dae7761ae663f89495

3 / The verified repair

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

N = 1
observations = []
def solve(segs):
    out = []
    cur = None
    starts = {'A': 103, 'B': 104, 'C': 105}
    switch = {'A': 101, 'B': 100, 'C': 99}
    def val(s, ch):
        o = ord(ch)
        if s == 'A':
            if 32 <= o <= 95:
                return o - 32
            if 0 <= o <= 31:
                return o + 64
            return None
        if 32 <= o <= 127:
            return o - 32
        return None
    for seg in segs:
        kind = seg[0]
        if kind == 'FNC1':
            if cur is None:
                return {'error': 'no-start'}
            out.append(102)
            continue
        if kind == 'SHIFT':
            if cur not in ('A', 'B'):
                return {'error': 'bad-shift'}
            other = 'B' if cur == 'A' else 'A'
            v = val(other, seg[1])
            if v is None:
                return {'error': 'unencodable', 'char': seg[1]}
            out += [98, v]
            continue
        s, text = seg
        if cur is None:
            out.append(starts[s])
        elif s != cur:
            out.append(switch[s])
        cur = s
        if s == 'C':
            if len(text) % 2 or not all(c in '0123456789' for c in text):
                return {'error': 'bad-c'}
            out += [int(text[j:j + 2]) for j in range(0, len(text), 2)]
        else:
            for ch in text:
                v = val(s, ch)
                if v is None:
                    return {'error': 'unencodable', 'char': ch}
                out.append(v)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['FNC1'], ['B', 'Lot 7'], ['A', '\x00Q']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'z'], ['C', '123']], {'error': 'no-start'}], [[['C', '12'], ['A', 'HELLO']], [105, 12, 101, 40, 37, 44, 44, 47]], [[['B', 'Q'], ['B', '{x}'], ['C', '123']], {'error': 'bad-c'}], [[['B', '{x}'], ['SHIFT', '\t'], ['C', '1'], ['A', '\x00Q']], {'error': 'bad-c'}], [[['B', 'ab'], ['A', '\x00Q'], ['SHIFT', '\t'], ['FNC1']], {'error': 'unencodable', 'char': '\t'}], [[['C', '123'], ['FNC1']], {'error': 'bad-c'}], [[['FNC1'], ['A', '\t']], {'error': 'no-start'}]], [[[['FNC1'], ['B', 'z~'], ['B', 'Q'], ['FNC1'], ['A', '\x00Q']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'a']], {'error': 'no-start'}], [[['C', '1'], ['C', '12']], {'error': 'bad-c'}], [[['A', '\x00Q'], ['B', '{x}'], ['A', 'X\x1d1'], ['SHIFT', 'z']], [103, 64, 49, 100, 91, 88, 93, 101, 56, 93, 17, 98, 90]], [[['A', 'AB'], ['B', 'Q'], ['B', 'z~']], [103, 33, 34, 100, 49, 90, 94]], [[['A', 'AB'], ['FNC1']], [103, 33, 34, 102]], [[['B', 'z~'], ['SHIFT', 'z'], ['FNC1']], {'error': 'unencodable', 'char': 'z'}], [[['FNC1'], ['B', 'Lot 7']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', 'a'], ['C', '1'], ['FNC1']], {'error': 'no-start'}], [[['FNC1'], ['B', 'z~']], {'error': 'no-start'}], [[['B', 'Lot 7']], [104, 44, 79, 84, 0, 23]], [[['C', '0099']], [105, 0, 99]], [[['A', 'AB']], [103, 33, 34]], [[['A', 'X\x1d1']], [103, 56, 93, 17]], [[['C', '12']], [105, 12]], [[['FNC1'], ['FNC1'], ['A', 'HELLO'], ['C', '4711']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', 'z'], ['FNC1']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', 'B']], {'error': 'no-start'}], [[['B', 'Lot 7'], ['C', ' 1'], ['A', 'AB'], ['B', 'ab']], {'error': 'bad-c'}], [[['C', '4711'], ['B', 'ab'], ['A', 'X\x1d1']], [105, 47, 11, 100, 65, 66, 101, 56, 93, 17]], [[['B', 'z~']], [104, 90, 94]], [[['C', ' 1'], ['FNC1'], ['C', ' 1'], ['A', '_^']], {'error': 'bad-c'}], [[['C', ' 1'], ['C', '0099']], {'error': 'bad-c'}], [[['FNC1'], ['A', '\t'], ['A', 'A`']], {'error': 'no-start'}]], [[[['FNC1'], ['SHIFT', '\x1d'], ['B', 'z~'], ['A', 'AB']], {'error': 'no-start'}], [[['FNC1'], ['SHIFT', '\x1d']], {'error': 'no-start'}], [[['B', 'Q']], [104, 49]], [[['A', '\t'], ['C', '0099']], [103, 73, 99, 0, 99]], [[['C', '4711'], ['B', 'Q'], ['B', '{x}']], [105, 47, 11, 100, 49, 91, 88, 93]], [[['B', '{x}'], ['B', 'Q']], [104, 91, 88, 93, 49]], [[['A', 'AB']], [103, 33, 34]], [[['FNC1'], ['A', 'X\x1d1']], {'error': 'no-start'}]]]
labels = ["regression: FNC1 before a start character", "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: FNC1 before a start character 0{'error': 'no-start'}{'error': 'no-start'}Passed
repair trap 1{'error': 'no-start'}{'error': 'no-start'}Passed
combined fault 2[105, 12, 101, 40, 37, 44, 44, 47][105, 12, 101, 40, 37, 44, 44, 47]Passed
control 3{'error': 'bad-c'}{'error': 'bad-c'}Passed
control 4{'error': 'bad-c'}{'error': 'bad-c'}Passed
boundary 5{'char': '\t', 'error': 'unencodable'}{'char': '\t', 'error': 'unencodable'}Passed
boundary 6{'error': 'bad-c'}{'error': 'bad-c'}Passed
control 7{'error': 'no-start'}{'error': 'no-start'}Passed

SHA-256 / 750880576bf7a4598385d9806dca33a31d7bf0b5bc5d5cea3f95f11288721f8a

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

Case digest / 6958145c976d0681415a03b392f08e3e4dac45ee0c8e16aa1c92316355cfa75a