FAILURE MAP
← Case archive

FA-72421 / Check-digit algorithms / Open access

ISBN-10 weights start at nine · case 01

Correct ISBNs are rejected and some typos are accepted.

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

ROOT CAUSE

The weight is 9 - i, so the check character gets weight 0 and every other weight is one short.

VERIFIED REPAIR

Weight position i (from the left, 0-based) by 10 - i.

Unsuccessful approach: Using 11 - i adds an unweighted digit sum to the total and still fails the mod-11 test.

Case contract

ISBN-10 validation. Hyphens and spaces are removed; the rest must be nine ASCII digits followed by a digit or uppercase X (value 10), else "malformed". Weights run 10 down to 1 from the left and the number is "valid" when the weighted sum is divisible by 11, else "invalid".

Why this case matters

Catalogue and bookstore systems validate legacy ISBN-10 identifiers on intake.

1 / The failure

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

N = 1
observations = []
def solve(s):
    t = s.replace('-', '').replace(' ', '')
    if len(t) != 10 or not t.isascii() or not t[:9].isdigit():
        return 'malformed'
    if not (t[9].isdigit() or t[9] == 'X'):
        return 'malformed'
    total = 0
    for i, ch in enumerate(t):
        v = 10 if ch == 'X' else int(ch)
        total += (9 - i) * v
    return 'valid' if total % 11 == 0 else 'invalid'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["5892872939"]', ['5892872939'], 'valid'], ['regression ["2399553950"]', ['2399553950'], 'valid'], ['control ["9465545449"]', ['9465545449'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid'], ['control ["0000000000"]', ['0000000000'], 'valid'], ['control ["123456789X"]', ['123456789X'], 'valid'], ['control ["2399553951"]', ['2399553951'], 'invalid'], ['control ["8292844660"]', ['8292844660'], 'invalid']], [['regression ["9379774826"]', ['9379774826'], 'valid'], ['regression ["2892681790"]', ['2892681790'], 'valid'], ['control ["8292844660"]', ['8292844660'], 'invalid'], ['control ["9379774827"]', ['9379774827'], 'invalid'], ['control ["2892681791"]', ['2892681791'], 'invalid'], ['control ["5900307906"]', ['5900307906'], 'invalid'], ['control ["9-465-54544-9"]', ['9-465-54544-9'], 'valid'], ['control ["2-266-68568-6"]', ['2-266-68568-6'], 'valid']], [['regression ["3905987139"]', ['3905987139'], 'valid'], ['regression ["7113753523"]', ['7113753523'], 'valid'], ['control ["2-266-68568-6"]', ['2-266-68568-6'], 'valid'], ['control ["5892872938"]', ['5892872938'], 'invalid'], ['control ["8292844669"]', ['8292844669'], 'invalid'], ['control ["9379774825"]', ['9379774825'], 'invalid'], ['control ["5900307904"]', ['5900307904'], 'invalid'], ['control ["0306406153"]', ['0306406153'], 'invalid']], [['regression ["3407375115"]', ['3407375115'], 'valid'], ['regression ["8449627923"]', ['8449627923'], 'valid'], ['control ["0306406153"]', ['0306406153'], 'invalid'], ['control ["03064061"]', ['03064061'], 'malformed'], ['control ["030640615X1"]', ['030640615X1'], 'malformed'], ['control ["0306406X52"]', ['0306406X52'], 'malformed'], ['control ["9465545449"]', ['9465545449'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid']], [['regression ["080442957X"]', ['080442957X'], 'valid'], ['regression ["0306406152"]', ['0306406152'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid'], ['control ["0000000000"]', ['0000000000'], 'valid'], ['control ["123456789X"]', ['123456789X'], 'valid'], ['control ["2399553951"]', ['2399553951'], 'invalid'], ['control ["8292844660"]', ['8292844660'], 'invalid'], ['control ["9379774827"]', ['9379774827'], 'invalid']]]
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 fixtureActualExpectedOutcome
regression ["5892872939"]invalidvalidFailed
regression ["2399553950"]invalidvalidFailed
control ["9465545449"]validvalidPassed
control ["2266685686"]validvalidPassed
control ["0000000000"]validvalidPassed
control ["123456789X"]validvalidPassed
control ["2399553951"]invalidinvalidPassed
control ["8292844660"]invalidinvalidPassed

SHA-256 / 6a619d10468e6eb296f168069aa3d39b2a1d63f377275bdff6b4c3ce61867cbf

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(s):
    t = s.replace('-', '').replace(' ', '')
    if len(t) != 10 or not t.isascii() or not t[:9].isdigit():
        return 'malformed'
    if not (t[9].isdigit() or t[9] == 'X'):
        return 'malformed'
    total = 0
    for i, ch in enumerate(t):
        v = 10 if ch == 'X' else int(ch)
        total += (11 - i) * v
    return 'valid' if total % 11 == 0 else 'invalid'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["5892872939"]', ['5892872939'], 'valid'], ['regression ["2399553950"]', ['2399553950'], 'valid'], ['control ["9465545449"]', ['9465545449'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid'], ['control ["0000000000"]', ['0000000000'], 'valid'], ['control ["123456789X"]', ['123456789X'], 'valid'], ['control ["2399553951"]', ['2399553951'], 'invalid'], ['control ["8292844660"]', ['8292844660'], 'invalid']], [['regression ["9379774826"]', ['9379774826'], 'valid'], ['regression ["2892681790"]', ['2892681790'], 'valid'], ['control ["8292844660"]', ['8292844660'], 'invalid'], ['control ["9379774827"]', ['9379774827'], 'invalid'], ['control ["2892681791"]', ['2892681791'], 'invalid'], ['control ["5900307906"]', ['5900307906'], 'invalid'], ['control ["9-465-54544-9"]', ['9-465-54544-9'], 'valid'], ['control ["2-266-68568-6"]', ['2-266-68568-6'], 'valid']], [['regression ["3905987139"]', ['3905987139'], 'valid'], ['regression ["7113753523"]', ['7113753523'], 'valid'], ['control ["2-266-68568-6"]', ['2-266-68568-6'], 'valid'], ['control ["5892872938"]', ['5892872938'], 'invalid'], ['control ["8292844669"]', ['8292844669'], 'invalid'], ['control ["9379774825"]', ['9379774825'], 'invalid'], ['control ["5900307904"]', ['5900307904'], 'invalid'], ['control ["0306406153"]', ['0306406153'], 'invalid']], [['regression ["3407375115"]', ['3407375115'], 'valid'], ['regression ["8449627923"]', ['8449627923'], 'valid'], ['control ["0306406153"]', ['0306406153'], 'invalid'], ['control ["03064061"]', ['03064061'], 'malformed'], ['control ["030640615X1"]', ['030640615X1'], 'malformed'], ['control ["0306406X52"]', ['0306406X52'], 'malformed'], ['control ["9465545449"]', ['9465545449'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid']], [['regression ["080442957X"]', ['080442957X'], 'valid'], ['regression ["0306406152"]', ['0306406152'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid'], ['control ["0000000000"]', ['0000000000'], 'valid'], ['control ["123456789X"]', ['123456789X'], 'valid'], ['control ["2399553951"]', ['2399553951'], 'invalid'], ['control ["8292844660"]', ['8292844660'], 'invalid'], ['control ["9379774827"]', ['9379774827'], 'invalid']]]
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 fixtureActualExpectedOutcome
regression ["5892872939"]invalidvalidFailed
regression ["2399553950"]invalidvalidFailed
control ["9465545449"]validvalidPassed
control ["2266685686"]validvalidPassed
control ["0000000000"]validvalidPassed
control ["123456789X"]validvalidPassed
control ["2399553951"]invalidinvalidPassed
control ["8292844660"]invalidinvalidPassed

SHA-256 / f5916e580b2f66c521d660d39a1dd879980ea0b4a2bfe4b00505a1654a6043e3

3 / The verified repair

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

N = 1
observations = []
def solve(s):
    t = s.replace('-', '').replace(' ', '')
    if len(t) != 10 or not t.isascii() or not t[:9].isdigit():
        return 'malformed'
    if not (t[9].isdigit() or t[9] == 'X'):
        return 'malformed'
    total = 0
    for i, ch in enumerate(t):
        v = 10 if ch == 'X' else int(ch)
        total += (10 - i) * v
    return 'valid' if total % 11 == 0 else 'invalid'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["5892872939"]', ['5892872939'], 'valid'], ['regression ["2399553950"]', ['2399553950'], 'valid'], ['control ["9465545449"]', ['9465545449'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid'], ['control ["0000000000"]', ['0000000000'], 'valid'], ['control ["123456789X"]', ['123456789X'], 'valid'], ['control ["2399553951"]', ['2399553951'], 'invalid'], ['control ["8292844660"]', ['8292844660'], 'invalid']], [['regression ["9379774826"]', ['9379774826'], 'valid'], ['regression ["2892681790"]', ['2892681790'], 'valid'], ['control ["8292844660"]', ['8292844660'], 'invalid'], ['control ["9379774827"]', ['9379774827'], 'invalid'], ['control ["2892681791"]', ['2892681791'], 'invalid'], ['control ["5900307906"]', ['5900307906'], 'invalid'], ['control ["9-465-54544-9"]', ['9-465-54544-9'], 'valid'], ['control ["2-266-68568-6"]', ['2-266-68568-6'], 'valid']], [['regression ["3905987139"]', ['3905987139'], 'valid'], ['regression ["7113753523"]', ['7113753523'], 'valid'], ['control ["2-266-68568-6"]', ['2-266-68568-6'], 'valid'], ['control ["5892872938"]', ['5892872938'], 'invalid'], ['control ["8292844669"]', ['8292844669'], 'invalid'], ['control ["9379774825"]', ['9379774825'], 'invalid'], ['control ["5900307904"]', ['5900307904'], 'invalid'], ['control ["0306406153"]', ['0306406153'], 'invalid']], [['regression ["3407375115"]', ['3407375115'], 'valid'], ['regression ["8449627923"]', ['8449627923'], 'valid'], ['control ["0306406153"]', ['0306406153'], 'invalid'], ['control ["03064061"]', ['03064061'], 'malformed'], ['control ["030640615X1"]', ['030640615X1'], 'malformed'], ['control ["0306406X52"]', ['0306406X52'], 'malformed'], ['control ["9465545449"]', ['9465545449'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid']], [['regression ["080442957X"]', ['080442957X'], 'valid'], ['regression ["0306406152"]', ['0306406152'], 'valid'], ['control ["2266685686"]', ['2266685686'], 'valid'], ['control ["0000000000"]', ['0000000000'], 'valid'], ['control ["123456789X"]', ['123456789X'], 'valid'], ['control ["2399553951"]', ['2399553951'], 'invalid'], ['control ["8292844660"]', ['8292844660'], 'invalid'], ['control ["9379774827"]', ['9379774827'], 'invalid']]]
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 fixtureActualExpectedOutcome
regression ["5892872939"]validvalidPassed
regression ["2399553950"]validvalidPassed
control ["9465545449"]validvalidPassed
control ["2266685686"]validvalidPassed
control ["0000000000"]validvalidPassed
control ["123456789X"]validvalidPassed
control ["2399553951"]invalidinvalidPassed
control ["8292844660"]invalidinvalidPassed

SHA-256 / a6bbe916da7da4c180843518e2965d632fecb3a695552e014ff900a02ec29034

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

Case digest / 2fac6e6915cf633b6448b66363046a157b83cfa3159f29a9c36ca5b0a85493cb