FAILURE MAP
← Case archive

FA-72766 / Check-digit algorithms / Open access

Visa routing rejects nineteen-digit cards · case 01

Long-format Visa cards are reported as unknown.

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

ROOT CAUSE

The Visa length set only contains 16.

VERIFIED REPAIR

Accept Visa numbers of 13, 16 or 19 digits.

Unsuccessful approach: Adding 13 but not 19 still misses long-format cards.

Case contract

Card number screening: spaces removed, nonempty ASCII digits required (else "malformed"). Network by prefix and length: visa 4 with 13/16/19 digits; amex 34 or 37 with 15; mastercard 51-55 or 2221-2720 with 16; discover 6011, 644-649 or 65 with 16-19; otherwise "unknown". Return [network, Luhn validity].

Why this case matters

Checkout forms route card numbers to the right processor and reject Luhn failures before authorization.

1 / The failure

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

N = 1
observations = []
def solve(s):
    t = s.replace(' ', '')
    if not t or not t.isascii() or not t.isdigit():
        return 'malformed'
    n = len(t)
    if t[0] == '4' and n == 16:
        net = 'visa'
    elif t[:2] in ('34', '37') and n == 15:
        net = 'amex'
    elif (51 <= int(t[:2]) <= 55 or 2221 <= int(t[:4]) <= 2720) and n == 16:
        net = 'mastercard'
    elif (t[:4] == '6011' or 644 <= int(t[:3]) <= 649 or t[:2] == '65') and 16 <= n <= 19:
        net = 'discover'
    else:
        net = 'unknown'
    total = 0
    for i, ch in enumerate(reversed(t)):
        d = int(ch) * (2 if i % 2 else 1)
        total += d - 9 if d > 9 else d
    return [net, total % 10 == 0]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["4846348185497646"]', ['4846348185497646'], ['visa', False]], ['control ["341466066267172"]', ['341466066267172'], ['amex', False]], ['control ["376431358491919"]', ['376431358491919'], ['amex', False]], ['control ["351552971521401"]', ['351552971521401'], ['unknown', True]], ['control ["367788575584486"]', ['367788575584486'], ['unknown', False]], ['control ["5168420993367718"]', ['5168420993367718'], ['mastercard', False]]], [['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['control ["5168420993367718"]', ['5168420993367718'], ['mastercard', False]], ['control ["5518245380112330"]', ['5518245380112330'], ['mastercard', False]], ['control ["5656984207856782"]', ['5656984207856782'], ['unknown', False]], ['control ["2221631854572594"]', ['2221631854572594'], ['mastercard', False]], ['control ["2720611269032342"]', ['2720611269032342'], ['mastercard', False]], ['control ["2721101650461399"]', ['2721101650461399'], ['unknown', False]]], [['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["2721101650461399"]', ['2721101650461399'], ['unknown', False]], ['control ["2719349847162292"]', ['2719349847162292'], ['mastercard', False]], ['control ["6011388299412119"]', ['6011388299412119'], ['discover', False]], ['control ["6441839750335463"]', ['6441839750335463'], ['discover', False]], ['control ["6490399248434857177"]', ['6490399248434857177'], ['discover', False]], ['control ["6408243514832764"]', ['6408243514832764'], ['unknown', False]]], [['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['control ["6408243514832764"]', ['6408243514832764'], ['unknown', False]], ['control ["6438800916518222"]', ['6438800916518222'], ['unknown', False]], ['control ["65813918194527509"]', ['65813918194527509'], ['discover', False]], ['control ["6692677811687578"]', ['6692677811687578'], ['unknown', True]], ['control ["4111 1111 1111 1111"]', ['4111 1111 1111 1111'], ['visa', True]], ['control ["378282246310005"]', ['378282246310005'], ['amex', True]]], [['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["378282246310005"]', ['378282246310005'], ['amex', True]], ['control ["5555555555554444"]', ['5555555555554444'], ['mastercard', True]], ['control ["2223003122003222"]', ['2223003122003222'], ['mastercard', True]], ['control ["6011111111111117"]', ['6011111111111117'], ['discover', True]], ['control ["4111-1111"]', ['4111-1111'], 'malformed'], ['control [""]', [''], 'malformed']]]
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 ["4677178611987"]['unknown', False]['visa', False]Failed
regression ["4654355756337734313"]['unknown', False]['visa', False]Failed
control ["4846348185497646"]['visa', False]['visa', False]Passed
control ["341466066267172"]['amex', False]['amex', False]Passed
control ["376431358491919"]['amex', False]['amex', False]Passed
control ["351552971521401"]['unknown', True]['unknown', True]Passed
control ["367788575584486"]['unknown', False]['unknown', False]Passed
control ["5168420993367718"]['mastercard', False]['mastercard', False]Passed

SHA-256 / 3203b10ce5f904d59b32153eef4e3d62b54b85ad55e03e6ca5ca7396064c2a38

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(' ', '')
    if not t or not t.isascii() or not t.isdigit():
        return 'malformed'
    n = len(t)
    if t[0] == '4' and n in (13, 16):
        net = 'visa'
    elif t[:2] in ('34', '37') and n == 15:
        net = 'amex'
    elif (51 <= int(t[:2]) <= 55 or 2221 <= int(t[:4]) <= 2720) and n == 16:
        net = 'mastercard'
    elif (t[:4] == '6011' or 644 <= int(t[:3]) <= 649 or t[:2] == '65') and 16 <= n <= 19:
        net = 'discover'
    else:
        net = 'unknown'
    total = 0
    for i, ch in enumerate(reversed(t)):
        d = int(ch) * (2 if i % 2 else 1)
        total += d - 9 if d > 9 else d
    return [net, total % 10 == 0]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["4846348185497646"]', ['4846348185497646'], ['visa', False]], ['control ["341466066267172"]', ['341466066267172'], ['amex', False]], ['control ["376431358491919"]', ['376431358491919'], ['amex', False]], ['control ["351552971521401"]', ['351552971521401'], ['unknown', True]], ['control ["367788575584486"]', ['367788575584486'], ['unknown', False]], ['control ["5168420993367718"]', ['5168420993367718'], ['mastercard', False]]], [['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['control ["5168420993367718"]', ['5168420993367718'], ['mastercard', False]], ['control ["5518245380112330"]', ['5518245380112330'], ['mastercard', False]], ['control ["5656984207856782"]', ['5656984207856782'], ['unknown', False]], ['control ["2221631854572594"]', ['2221631854572594'], ['mastercard', False]], ['control ["2720611269032342"]', ['2720611269032342'], ['mastercard', False]], ['control ["2721101650461399"]', ['2721101650461399'], ['unknown', False]]], [['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["2721101650461399"]', ['2721101650461399'], ['unknown', False]], ['control ["2719349847162292"]', ['2719349847162292'], ['mastercard', False]], ['control ["6011388299412119"]', ['6011388299412119'], ['discover', False]], ['control ["6441839750335463"]', ['6441839750335463'], ['discover', False]], ['control ["6490399248434857177"]', ['6490399248434857177'], ['discover', False]], ['control ["6408243514832764"]', ['6408243514832764'], ['unknown', False]]], [['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['control ["6408243514832764"]', ['6408243514832764'], ['unknown', False]], ['control ["6438800916518222"]', ['6438800916518222'], ['unknown', False]], ['control ["65813918194527509"]', ['65813918194527509'], ['discover', False]], ['control ["6692677811687578"]', ['6692677811687578'], ['unknown', True]], ['control ["4111 1111 1111 1111"]', ['4111 1111 1111 1111'], ['visa', True]], ['control ["378282246310005"]', ['378282246310005'], ['amex', True]]], [['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["378282246310005"]', ['378282246310005'], ['amex', True]], ['control ["5555555555554444"]', ['5555555555554444'], ['mastercard', True]], ['control ["2223003122003222"]', ['2223003122003222'], ['mastercard', True]], ['control ["6011111111111117"]', ['6011111111111117'], ['discover', True]], ['control ["4111-1111"]', ['4111-1111'], 'malformed'], ['control [""]', [''], 'malformed']]]
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 ["4677178611987"]['visa', False]['visa', False]Passed
regression ["4654355756337734313"]['unknown', False]['visa', False]Failed
control ["4846348185497646"]['visa', False]['visa', False]Passed
control ["341466066267172"]['amex', False]['amex', False]Passed
control ["376431358491919"]['amex', False]['amex', False]Passed
control ["351552971521401"]['unknown', True]['unknown', True]Passed
control ["367788575584486"]['unknown', False]['unknown', False]Passed
control ["5168420993367718"]['mastercard', False]['mastercard', False]Passed

SHA-256 / 43642a35784818fd5b1d0b6414f6284d50434632e676f68b977479df517ae1bb

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(' ', '')
    if not t or not t.isascii() or not t.isdigit():
        return 'malformed'
    n = len(t)
    if t[0] == '4' and n in (13, 16, 19):
        net = 'visa'
    elif t[:2] in ('34', '37') and n == 15:
        net = 'amex'
    elif (51 <= int(t[:2]) <= 55 or 2221 <= int(t[:4]) <= 2720) and n == 16:
        net = 'mastercard'
    elif (t[:4] == '6011' or 644 <= int(t[:3]) <= 649 or t[:2] == '65') and 16 <= n <= 19:
        net = 'discover'
    else:
        net = 'unknown'
    total = 0
    for i, ch in enumerate(reversed(t)):
        d = int(ch) * (2 if i % 2 else 1)
        total += d - 9 if d > 9 else d
    return [net, total % 10 == 0]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["4846348185497646"]', ['4846348185497646'], ['visa', False]], ['control ["341466066267172"]', ['341466066267172'], ['amex', False]], ['control ["376431358491919"]', ['376431358491919'], ['amex', False]], ['control ["351552971521401"]', ['351552971521401'], ['unknown', True]], ['control ["367788575584486"]', ['367788575584486'], ['unknown', False]], ['control ["5168420993367718"]', ['5168420993367718'], ['mastercard', False]]], [['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['control ["5168420993367718"]', ['5168420993367718'], ['mastercard', False]], ['control ["5518245380112330"]', ['5518245380112330'], ['mastercard', False]], ['control ["5656984207856782"]', ['5656984207856782'], ['unknown', False]], ['control ["2221631854572594"]', ['2221631854572594'], ['mastercard', False]], ['control ["2720611269032342"]', ['2720611269032342'], ['mastercard', False]], ['control ["2721101650461399"]', ['2721101650461399'], ['unknown', False]]], [['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["2721101650461399"]', ['2721101650461399'], ['unknown', False]], ['control ["2719349847162292"]', ['2719349847162292'], ['mastercard', False]], ['control ["6011388299412119"]', ['6011388299412119'], ['discover', False]], ['control ["6441839750335463"]', ['6441839750335463'], ['discover', False]], ['control ["6490399248434857177"]', ['6490399248434857177'], ['discover', False]], ['control ["6408243514832764"]', ['6408243514832764'], ['unknown', False]]], [['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['control ["6408243514832764"]', ['6408243514832764'], ['unknown', False]], ['control ["6438800916518222"]', ['6438800916518222'], ['unknown', False]], ['control ["65813918194527509"]', ['65813918194527509'], ['discover', False]], ['control ["6692677811687578"]', ['6692677811687578'], ['unknown', True]], ['control ["4111 1111 1111 1111"]', ['4111 1111 1111 1111'], ['visa', True]], ['control ["378282246310005"]', ['378282246310005'], ['amex', True]]], [['regression ["4677178611987"]', ['4677178611987'], ['visa', False]], ['regression ["4654355756337734313"]', ['4654355756337734313'], ['visa', False]], ['control ["378282246310005"]', ['378282246310005'], ['amex', True]], ['control ["5555555555554444"]', ['5555555555554444'], ['mastercard', True]], ['control ["2223003122003222"]', ['2223003122003222'], ['mastercard', True]], ['control ["6011111111111117"]', ['6011111111111117'], ['discover', True]], ['control ["4111-1111"]', ['4111-1111'], 'malformed'], ['control [""]', [''], 'malformed']]]
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 ["4677178611987"]['visa', False]['visa', False]Passed
regression ["4654355756337734313"]['visa', False]['visa', False]Passed
control ["4846348185497646"]['visa', False]['visa', False]Passed
control ["341466066267172"]['amex', False]['amex', False]Passed
control ["376431358491919"]['amex', False]['amex', False]Passed
control ["351552971521401"]['unknown', True]['unknown', True]Passed
control ["367788575584486"]['unknown', False]['unknown', False]Passed
control ["5168420993367718"]['mastercard', False]['mastercard', False]Passed

SHA-256 / a175ae65a628118a49b6b92af23b4b7420b787c656fdc72eb4cacbd7a6e00cc1

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

Case digest / 6c40fb07a39931323a259ac4c645f57d4c38280db6e1793c682d310096f7a51c