FA-72456 / Check-digit algorithms / Open access
GTIN validator rejects GTIN-8 and GTIN-14 · case 01
Short-format and case-level codes are reported malformed.
ROOT CAUSE
The length gate only allows 12 and 13 digits.
VERIFIED REPAIR
Accept the four GTIN lengths 8, 12, 13 and 14.
Unsuccessful approach: Adding GTIN-8 but not GTIN-14 still rejects outer-case codes.
Case contract
Validate a GTIN-8, GTIN-12, GTIN-13 or GTIN-14 given as ASCII digits (any other length or character: "malformed"). Weights 3,1 alternate starting with 3 on the digit immediately left of the check digit, so the alignment is from the right for every length. Return [kind, check digit matches].
Why this case matters
Retail and logistics scanners accept several GTIN lengths through one validator.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
if not s.isascii() or not s.isdigit() or len(s) not in (12, 13):
return 'malformed'
body = s[:-1]
total = 0
for i, ch in enumerate(reversed(body)):
total += int(ch) * (3 if i % 2 == 0 else 1)
check = (10 - total % 10) % 10
kind = {8: 'GTIN-8', 12: 'GTIN-12', 13: 'GTIN-13', 14: 'GTIN-14'}[len(s)]
return [kind, check == int(s[-1])]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["07251955"]', ['07251955'], ['GTIN-8', True]], ['regression ["07251952"]', ['07251952'], ['GTIN-8', False]], ['partial-repair ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['partial-repair ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['control ["934235100467"]', ['934235100467'], ['GTIN-12', True]], ['control ["934235100464"]', ['934235100464'], ['GTIN-12', False]], ['control ["0916391037047"]', ['0916391037047'], ['GTIN-13', True]], ['control ["0916391037044"]', ['0916391037044'], ['GTIN-13', False]]], [['regression ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['regression ["12641161"]', ['12641161'], ['GTIN-8', True]], ['partial-repair ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['partial-repair ["10614141000415"]', ['10614141000415'], ['GTIN-14', True]], ['control ["8847703723459"]', ['8847703723459'], ['GTIN-13', False]], ['control ["033345301891"]', ['033345301891'], ['GTIN-12', True]], ['control ["033345301898"]', ['033345301898'], ['GTIN-12', False]], ['control ["6916522076161"]', ['6916522076161'], ['GTIN-13', True]]], [['regression ["84650644669471"]', ['84650644669471'], ['GTIN-14', True]], ['regression ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['partial-repair ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['control ["4006381333931"]', ['4006381333931'], ['GTIN-13', True]], ['control ["036000291452"]', ['036000291452'], ['GTIN-12', True]], ['control ["4006381333932"]', ['4006381333932'], ['GTIN-13', False]], ['control ["0"]', ['0'], 'malformed'], ['control ["123456789012345"]', ['123456789012345'], 'malformed']], [['regression ["10614141000415"]', ['10614141000415'], ['GTIN-14', True]], ['regression ["00000000"]', ['00000000'], ['GTIN-8', True]], ['partial-repair ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['control ["400638133393"]', ['400638133393'], ['GTIN-12', False]], ['control ["40063813339a1"]', ['40063813339a1'], 'malformed'], ['control ["9780306406157"]', ['9780306406157'], ['GTIN-13', True]], ['control ["5901234123457"]', ['5901234123457'], ['GTIN-13', True]], ['control ["934235100467"]', ['934235100467'], ['GTIN-12', True]]], [['regression ["07251952"]', ['07251952'], ['GTIN-8', False]], ['regression ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['partial-repair ["84650644669471"]', ['84650644669471'], ['GTIN-14', True]], ['partial-repair ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['control ["934235100464"]', ['934235100464'], ['GTIN-12', False]], ['control ["0916391037047"]', ['0916391037047'], ['GTIN-13', True]], ['control ["0916391037044"]', ['0916391037044'], ['GTIN-13', False]], ['control ["8847703723452"]', ['8847703723452'], ['GTIN-13', True]]]]
for label, args, expected in fixtures[N - 1]:
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression ["07251955"] | malformed | ['GTIN-8', True] | Failed |
| regression ["07251952"] | malformed | ['GTIN-8', False] | Failed |
| partial-repair ["59804222888448"] | malformed | ['GTIN-14', True] | Failed |
| partial-repair ["59804222888445"] | malformed | ['GTIN-14', False] | Failed |
| control ["934235100467"] | ['GTIN-12', True] | ['GTIN-12', True] | Passed |
| control ["934235100464"] | ['GTIN-12', False] | ['GTIN-12', False] | Passed |
| control ["0916391037047"] | ['GTIN-13', True] | ['GTIN-13', True] | Passed |
| control ["0916391037044"] | ['GTIN-13', False] | ['GTIN-13', False] | Passed |
SHA-256 / 9da4b8c485d3c59f7e969071321e60e49f467d4609d278a7cd6efc95bbaf7d84
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
if not s.isascii() or not s.isdigit() or len(s) not in (8, 12, 13):
return 'malformed'
body = s[:-1]
total = 0
for i, ch in enumerate(reversed(body)):
total += int(ch) * (3 if i % 2 == 0 else 1)
check = (10 - total % 10) % 10
kind = {8: 'GTIN-8', 12: 'GTIN-12', 13: 'GTIN-13', 14: 'GTIN-14'}[len(s)]
return [kind, check == int(s[-1])]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["07251955"]', ['07251955'], ['GTIN-8', True]], ['regression ["07251952"]', ['07251952'], ['GTIN-8', False]], ['partial-repair ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['partial-repair ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['control ["934235100467"]', ['934235100467'], ['GTIN-12', True]], ['control ["934235100464"]', ['934235100464'], ['GTIN-12', False]], ['control ["0916391037047"]', ['0916391037047'], ['GTIN-13', True]], ['control ["0916391037044"]', ['0916391037044'], ['GTIN-13', False]]], [['regression ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['regression ["12641161"]', ['12641161'], ['GTIN-8', True]], ['partial-repair ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['partial-repair ["10614141000415"]', ['10614141000415'], ['GTIN-14', True]], ['control ["8847703723459"]', ['8847703723459'], ['GTIN-13', False]], ['control ["033345301891"]', ['033345301891'], ['GTIN-12', True]], ['control ["033345301898"]', ['033345301898'], ['GTIN-12', False]], ['control ["6916522076161"]', ['6916522076161'], ['GTIN-13', True]]], [['regression ["84650644669471"]', ['84650644669471'], ['GTIN-14', True]], ['regression ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['partial-repair ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['control ["4006381333931"]', ['4006381333931'], ['GTIN-13', True]], ['control ["036000291452"]', ['036000291452'], ['GTIN-12', True]], ['control ["4006381333932"]', ['4006381333932'], ['GTIN-13', False]], ['control ["0"]', ['0'], 'malformed'], ['control ["123456789012345"]', ['123456789012345'], 'malformed']], [['regression ["10614141000415"]', ['10614141000415'], ['GTIN-14', True]], ['regression ["00000000"]', ['00000000'], ['GTIN-8', True]], ['partial-repair ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['control ["400638133393"]', ['400638133393'], ['GTIN-12', False]], ['control ["40063813339a1"]', ['40063813339a1'], 'malformed'], ['control ["9780306406157"]', ['9780306406157'], ['GTIN-13', True]], ['control ["5901234123457"]', ['5901234123457'], ['GTIN-13', True]], ['control ["934235100467"]', ['934235100467'], ['GTIN-12', True]]], [['regression ["07251952"]', ['07251952'], ['GTIN-8', False]], ['regression ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['partial-repair ["84650644669471"]', ['84650644669471'], ['GTIN-14', True]], ['partial-repair ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['control ["934235100464"]', ['934235100464'], ['GTIN-12', False]], ['control ["0916391037047"]', ['0916391037047'], ['GTIN-13', True]], ['control ["0916391037044"]', ['0916391037044'], ['GTIN-13', False]], ['control ["8847703723452"]', ['8847703723452'], ['GTIN-13', True]]]]
for label, args, expected in fixtures[N - 1]:
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression ["07251955"] | ['GTIN-8', True] | ['GTIN-8', True] | Passed |
| regression ["07251952"] | ['GTIN-8', False] | ['GTIN-8', False] | Passed |
| partial-repair ["59804222888448"] | malformed | ['GTIN-14', True] | Failed |
| partial-repair ["59804222888445"] | malformed | ['GTIN-14', False] | Failed |
| control ["934235100467"] | ['GTIN-12', True] | ['GTIN-12', True] | Passed |
| control ["934235100464"] | ['GTIN-12', False] | ['GTIN-12', False] | Passed |
| control ["0916391037047"] | ['GTIN-13', True] | ['GTIN-13', True] | Passed |
| control ["0916391037044"] | ['GTIN-13', False] | ['GTIN-13', False] | Passed |
SHA-256 / 8209da9ee9bac7a4811d75fb0adf7e0f20b79d0d719bdab2f971b6b9ccd39c5a
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
if not s.isascii() or not s.isdigit() or len(s) not in (8, 12, 13, 14):
return 'malformed'
body = s[:-1]
total = 0
for i, ch in enumerate(reversed(body)):
total += int(ch) * (3 if i % 2 == 0 else 1)
check = (10 - total % 10) % 10
kind = {8: 'GTIN-8', 12: 'GTIN-12', 13: 'GTIN-13', 14: 'GTIN-14'}[len(s)]
return [kind, check == int(s[-1])]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["07251955"]', ['07251955'], ['GTIN-8', True]], ['regression ["07251952"]', ['07251952'], ['GTIN-8', False]], ['partial-repair ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['partial-repair ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['control ["934235100467"]', ['934235100467'], ['GTIN-12', True]], ['control ["934235100464"]', ['934235100464'], ['GTIN-12', False]], ['control ["0916391037047"]', ['0916391037047'], ['GTIN-13', True]], ['control ["0916391037044"]', ['0916391037044'], ['GTIN-13', False]]], [['regression ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['regression ["12641161"]', ['12641161'], ['GTIN-8', True]], ['partial-repair ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['partial-repair ["10614141000415"]', ['10614141000415'], ['GTIN-14', True]], ['control ["8847703723459"]', ['8847703723459'], ['GTIN-13', False]], ['control ["033345301891"]', ['033345301891'], ['GTIN-12', True]], ['control ["033345301898"]', ['033345301898'], ['GTIN-12', False]], ['control ["6916522076161"]', ['6916522076161'], ['GTIN-13', True]]], [['regression ["84650644669471"]', ['84650644669471'], ['GTIN-14', True]], ['regression ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['partial-repair ["59804222888445"]', ['59804222888445'], ['GTIN-14', False]], ['control ["4006381333931"]', ['4006381333931'], ['GTIN-13', True]], ['control ["036000291452"]', ['036000291452'], ['GTIN-12', True]], ['control ["4006381333932"]', ['4006381333932'], ['GTIN-13', False]], ['control ["0"]', ['0'], 'malformed'], ['control ["123456789012345"]', ['123456789012345'], 'malformed']], [['regression ["10614141000415"]', ['10614141000415'], ['GTIN-14', True]], ['regression ["00000000"]', ['00000000'], ['GTIN-8', True]], ['partial-repair ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['control ["400638133393"]', ['400638133393'], ['GTIN-12', False]], ['control ["40063813339a1"]', ['40063813339a1'], 'malformed'], ['control ["9780306406157"]', ['9780306406157'], ['GTIN-13', True]], ['control ["5901234123457"]', ['5901234123457'], ['GTIN-13', True]], ['control ["934235100467"]', ['934235100467'], ['GTIN-12', True]]], [['regression ["07251952"]', ['07251952'], ['GTIN-8', False]], ['regression ["59804222888448"]', ['59804222888448'], ['GTIN-14', True]], ['partial-repair ["84650644669471"]', ['84650644669471'], ['GTIN-14', True]], ['partial-repair ["84650644669478"]', ['84650644669478'], ['GTIN-14', False]], ['control ["934235100464"]', ['934235100464'], ['GTIN-12', False]], ['control ["0916391037047"]', ['0916391037047'], ['GTIN-13', True]], ['control ["0916391037044"]', ['0916391037044'], ['GTIN-13', False]], ['control ["8847703723452"]', ['8847703723452'], ['GTIN-13', True]]]]
for label, args, expected in fixtures[N - 1]:
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression ["07251955"] | ['GTIN-8', True] | ['GTIN-8', True] | Passed |
| regression ["07251952"] | ['GTIN-8', False] | ['GTIN-8', False] | Passed |
| partial-repair ["59804222888448"] | ['GTIN-14', True] | ['GTIN-14', True] | Passed |
| partial-repair ["59804222888445"] | ['GTIN-14', False] | ['GTIN-14', False] | Passed |
| control ["934235100467"] | ['GTIN-12', True] | ['GTIN-12', True] | Passed |
| control ["934235100464"] | ['GTIN-12', False] | ['GTIN-12', False] | Passed |
| control ["0916391037047"] | ['GTIN-13', True] | ['GTIN-13', True] | Passed |
| control ["0916391037044"] | ['GTIN-13', False] | ['GTIN-13', False] | Passed |
SHA-256 / e4e6b4330218d429b7e46309c8a910f266993c61f780f5da847833f1eddf5812
Verification & scope
A deterministic, bounded teaching model of the named scheme under the stated contract; not a certified validator. 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:48:38.640236+00:00.
Case digest / 45a830e66b2c0abc135c578efeabcf70580c40c225081dd146b2a1c249bbb0eb