FAILURE MAP
← Case archive

FA-96456 / Phone number formatting / Open access

Extension and dial-pause parser: overlong extensions are accepted · case 01

A seven-digit extension is accepted.

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

ROOT CAUSE

Only the lower bound of the extension length is checked.

THE FAILURE

Only the lower bound of the extension length is checked.

Unsuccessful approach: Using a strict upper bound rejects six-digit extensions.

Case contract

Strip and lowercase. Try markers in order: "," (pause), ";" (wait), "extension", "ext.", "ext", "#", "x" (ext); the first marker found at an index > 0 splits the string into main and extension. The main part keeps its digits; the extension is stripped and, when a marker was found, must be 1..6 digits. Return {"main", "ext", "mode"} or None.

Why this case matters

Extensions and pause characters decide what a softphone dials after the call connects; a wrong split rings the wrong desk.

1 / The failure

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

N = 1
observations = []
def solve(x):
    s = x.strip().lower()
    mode, main, ext = '', s, ''
    for token, kind in ((',', 'pause'), (';', 'wait'), ('extension', 'ext'), ('ext.', 'ext'), ('ext', 'ext'),
                        ('#', 'ext'), ('x', 'ext')):
        i = main.find(token)
        if i > 0:
            main, ext, mode = main[:i], main[i + len(token):], kind
            break
    digits = ''.join(c for c in main if c.isdigit())
    ext = ext.strip()
    if mode and not (ext.isdigit() and 1 <= len(ext)):
        return None
    return {'main': digits, 'ext': ext, 'mode': mode}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['dotted ext', '555-0115 ext. 11', {'main': '5550115', 'ext': '11', 'mode': 'ext'}], ['spelled extension', '555-0115 extension 1', {'main': '5550115', 'ext': '1', 'mode': 'ext'}], ['uppercase EXT', '555-0115 EXT 41', {'main': '5550115', 'ext': '41', 'mode': 'ext'}], ['x with a space', '555-0115 x 3', {'main': '5550115', 'ext': '3', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0115 x 1 2', None], ['comma pause', '555-0115,121', {'main': '5550115', 'ext': '121', 'mode': 'pause'}], ['semicolon wait', '555-0115;1', {'main': '5550115', 'ext': '1', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0115', {'main': '5550115', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0115', {'main': '5550115', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0115 x1234567', None], ['six-digit extension accepted', '555-0115 x123451', {'main': '5550115', 'ext': '123451', 'mode': 'ext'}]], [['dotted ext', '555-0126 ext. 12', {'main': '5550126', 'ext': '12', 'mode': 'ext'}], ['spelled extension', '555-0126 extension 2', {'main': '5550126', 'ext': '2', 'mode': 'ext'}], ['uppercase EXT', '555-0126 EXT 42', {'main': '5550126', 'ext': '42', 'mode': 'ext'}], ['x with a space', '555-0126 x 4', {'main': '5550126', 'ext': '4', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0126 x 1 2', None], ['comma pause', '555-0126,122', {'main': '5550126', 'ext': '122', 'mode': 'pause'}], ['semicolon wait', '555-0126;2', {'main': '5550126', 'ext': '2', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0126', {'main': '5550126', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0126', {'main': '5550126', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0126 x1234567', None], ['six-digit extension accepted', '555-0126 x123452', {'main': '5550126', 'ext': '123452', 'mode': 'ext'}]], [['dotted ext', '555-0137 ext. 13', {'main': '5550137', 'ext': '13', 'mode': 'ext'}], ['spelled extension', '555-0137 extension 3', {'main': '5550137', 'ext': '3', 'mode': 'ext'}], ['uppercase EXT', '555-0137 EXT 43', {'main': '5550137', 'ext': '43', 'mode': 'ext'}], ['x with a space', '555-0137 x 5', {'main': '5550137', 'ext': '5', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0137 x 1 2', None], ['comma pause', '555-0137,123', {'main': '5550137', 'ext': '123', 'mode': 'pause'}], ['semicolon wait', '555-0137;3', {'main': '5550137', 'ext': '3', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0137', {'main': '5550137', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0137', {'main': '5550137', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0137 x1234567', None], ['six-digit extension accepted', '555-0137 x123453', {'main': '5550137', 'ext': '123453', 'mode': 'ext'}]], [['dotted ext', '555-0148 ext. 14', {'main': '5550148', 'ext': '14', 'mode': 'ext'}], ['spelled extension', '555-0148 extension 4', {'main': '5550148', 'ext': '4', 'mode': 'ext'}], ['uppercase EXT', '555-0148 EXT 44', {'main': '5550148', 'ext': '44', 'mode': 'ext'}], ['x with a space', '555-0148 x 6', {'main': '5550148', 'ext': '6', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0148 x 1 2', None], ['comma pause', '555-0148,124', {'main': '5550148', 'ext': '124', 'mode': 'pause'}], ['semicolon wait', '555-0148;4', {'main': '5550148', 'ext': '4', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0148', {'main': '5550148', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0148', {'main': '5550148', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0148 x1234567', None], ['six-digit extension accepted', '555-0148 x123454', {'main': '5550148', 'ext': '123454', 'mode': 'ext'}]], [['dotted ext', '555-0159 ext. 15', {'main': '5550159', 'ext': '15', 'mode': 'ext'}], ['spelled extension', '555-0159 extension 5', {'main': '5550159', 'ext': '5', 'mode': 'ext'}], ['uppercase EXT', '555-0159 EXT 45', {'main': '5550159', 'ext': '45', 'mode': 'ext'}], ['x with a space', '555-0159 x 7', {'main': '5550159', 'ext': '7', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0159 x 1 2', None], ['comma pause', '555-0159,125', {'main': '5550159', 'ext': '125', 'mode': 'pause'}], ['semicolon wait', '555-0159;5', {'main': '5550159', 'ext': '5', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0159', {'main': '5550159', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0159', {'main': '5550159', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0159 x1234567', None], ['six-digit extension accepted', '555-0159 x123455', {'main': '5550159', 'ext': '123455', 'mode': 'ext'}]]]
for label, arg, expected in fixtures[N - 1]:
    check(label, solve(arg), 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
dotted ext{'ext': '11', 'main': '5550115', 'mode': 'ext'}{'ext': '11', 'main': '5550115', 'mode': 'ext'}Passed
spelled extension{'ext': '1', 'main': '5550115', 'mode': 'ext'}{'ext': '1', 'main': '5550115', 'mode': 'ext'}Passed
uppercase EXT{'ext': '41', 'main': '5550115', 'mode': 'ext'}{'ext': '41', 'main': '5550115', 'mode': 'ext'}Passed
x with a space{'ext': '3', 'main': '5550115', 'mode': 'ext'}{'ext': '3', 'main': '5550115', 'mode': 'ext'}Passed
spaced extension digits rejectedNoneNonePassed
comma pause{'ext': '121', 'main': '5550115', 'mode': 'pause'}{'ext': '121', 'main': '5550115', 'mode': 'pause'}Passed
semicolon wait{'ext': '1', 'main': '5550115', 'mode': 'wait'}{'ext': '1', 'main': '5550115', 'mode': 'wait'}Passed
leading hash is not an extension{'ext': '', 'main': '5550115', 'mode': ''}{'ext': '', 'main': '5550115', 'mode': ''}Passed
leading comma is not a pause{'ext': '', 'main': '5550115', 'mode': ''}{'ext': '', 'main': '5550115', 'mode': ''}Passed
seven-digit extension rejected{'ext': '1234567', 'main': '5550115', 'mode': 'ext'}NoneFailed
six-digit extension accepted{'ext': '123451', 'main': '5550115', 'mode': 'ext'}{'ext': '123451', 'main': '5550115', 'mode': 'ext'}Passed

SHA-256 / 4587f49e25e897b9638bed9ad4211aaf01a921997f07bca73c41d482c889ca36

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    s = x.strip().lower()
    mode, main, ext = '', s, ''
    for token, kind in ((',', 'pause'), (';', 'wait'), ('extension', 'ext'), ('ext.', 'ext'), ('ext', 'ext'),
                        ('#', 'ext'), ('x', 'ext')):
        i = main.find(token)
        if i > 0:
            main, ext, mode = main[:i], main[i + len(token):], kind
            break
    digits = ''.join(c for c in main if c.isdigit())
    ext = ext.strip()
    if mode and not (ext.isdigit() and 1 <= len(ext) < 6):
        return None
    return {'main': digits, 'ext': ext, 'mode': mode}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['dotted ext', '555-0115 ext. 11', {'main': '5550115', 'ext': '11', 'mode': 'ext'}], ['spelled extension', '555-0115 extension 1', {'main': '5550115', 'ext': '1', 'mode': 'ext'}], ['uppercase EXT', '555-0115 EXT 41', {'main': '5550115', 'ext': '41', 'mode': 'ext'}], ['x with a space', '555-0115 x 3', {'main': '5550115', 'ext': '3', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0115 x 1 2', None], ['comma pause', '555-0115,121', {'main': '5550115', 'ext': '121', 'mode': 'pause'}], ['semicolon wait', '555-0115;1', {'main': '5550115', 'ext': '1', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0115', {'main': '5550115', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0115', {'main': '5550115', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0115 x1234567', None], ['six-digit extension accepted', '555-0115 x123451', {'main': '5550115', 'ext': '123451', 'mode': 'ext'}]], [['dotted ext', '555-0126 ext. 12', {'main': '5550126', 'ext': '12', 'mode': 'ext'}], ['spelled extension', '555-0126 extension 2', {'main': '5550126', 'ext': '2', 'mode': 'ext'}], ['uppercase EXT', '555-0126 EXT 42', {'main': '5550126', 'ext': '42', 'mode': 'ext'}], ['x with a space', '555-0126 x 4', {'main': '5550126', 'ext': '4', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0126 x 1 2', None], ['comma pause', '555-0126,122', {'main': '5550126', 'ext': '122', 'mode': 'pause'}], ['semicolon wait', '555-0126;2', {'main': '5550126', 'ext': '2', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0126', {'main': '5550126', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0126', {'main': '5550126', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0126 x1234567', None], ['six-digit extension accepted', '555-0126 x123452', {'main': '5550126', 'ext': '123452', 'mode': 'ext'}]], [['dotted ext', '555-0137 ext. 13', {'main': '5550137', 'ext': '13', 'mode': 'ext'}], ['spelled extension', '555-0137 extension 3', {'main': '5550137', 'ext': '3', 'mode': 'ext'}], ['uppercase EXT', '555-0137 EXT 43', {'main': '5550137', 'ext': '43', 'mode': 'ext'}], ['x with a space', '555-0137 x 5', {'main': '5550137', 'ext': '5', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0137 x 1 2', None], ['comma pause', '555-0137,123', {'main': '5550137', 'ext': '123', 'mode': 'pause'}], ['semicolon wait', '555-0137;3', {'main': '5550137', 'ext': '3', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0137', {'main': '5550137', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0137', {'main': '5550137', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0137 x1234567', None], ['six-digit extension accepted', '555-0137 x123453', {'main': '5550137', 'ext': '123453', 'mode': 'ext'}]], [['dotted ext', '555-0148 ext. 14', {'main': '5550148', 'ext': '14', 'mode': 'ext'}], ['spelled extension', '555-0148 extension 4', {'main': '5550148', 'ext': '4', 'mode': 'ext'}], ['uppercase EXT', '555-0148 EXT 44', {'main': '5550148', 'ext': '44', 'mode': 'ext'}], ['x with a space', '555-0148 x 6', {'main': '5550148', 'ext': '6', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0148 x 1 2', None], ['comma pause', '555-0148,124', {'main': '5550148', 'ext': '124', 'mode': 'pause'}], ['semicolon wait', '555-0148;4', {'main': '5550148', 'ext': '4', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0148', {'main': '5550148', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0148', {'main': '5550148', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0148 x1234567', None], ['six-digit extension accepted', '555-0148 x123454', {'main': '5550148', 'ext': '123454', 'mode': 'ext'}]], [['dotted ext', '555-0159 ext. 15', {'main': '5550159', 'ext': '15', 'mode': 'ext'}], ['spelled extension', '555-0159 extension 5', {'main': '5550159', 'ext': '5', 'mode': 'ext'}], ['uppercase EXT', '555-0159 EXT 45', {'main': '5550159', 'ext': '45', 'mode': 'ext'}], ['x with a space', '555-0159 x 7', {'main': '5550159', 'ext': '7', 'mode': 'ext'}], ['spaced extension digits rejected', '555-0159 x 1 2', None], ['comma pause', '555-0159,125', {'main': '5550159', 'ext': '125', 'mode': 'pause'}], ['semicolon wait', '555-0159;5', {'main': '5550159', 'ext': '5', 'mode': 'wait'}], ['leading hash is not an extension', '#555-0159', {'main': '5550159', 'ext': '', 'mode': ''}], ['leading comma is not a pause', ',555-0159', {'main': '5550159', 'ext': '', 'mode': ''}], ['seven-digit extension rejected', '555-0159 x1234567', None], ['six-digit extension accepted', '555-0159 x123455', {'main': '5550159', 'ext': '123455', 'mode': 'ext'}]]]
for label, arg, expected in fixtures[N - 1]:
    check(label, solve(arg), 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
dotted ext{'ext': '11', 'main': '5550115', 'mode': 'ext'}{'ext': '11', 'main': '5550115', 'mode': 'ext'}Passed
spelled extension{'ext': '1', 'main': '5550115', 'mode': 'ext'}{'ext': '1', 'main': '5550115', 'mode': 'ext'}Passed
uppercase EXT{'ext': '41', 'main': '5550115', 'mode': 'ext'}{'ext': '41', 'main': '5550115', 'mode': 'ext'}Passed
x with a space{'ext': '3', 'main': '5550115', 'mode': 'ext'}{'ext': '3', 'main': '5550115', 'mode': 'ext'}Passed
spaced extension digits rejectedNoneNonePassed
comma pause{'ext': '121', 'main': '5550115', 'mode': 'pause'}{'ext': '121', 'main': '5550115', 'mode': 'pause'}Passed
semicolon wait{'ext': '1', 'main': '5550115', 'mode': 'wait'}{'ext': '1', 'main': '5550115', 'mode': 'wait'}Passed
leading hash is not an extension{'ext': '', 'main': '5550115', 'mode': ''}{'ext': '', 'main': '5550115', 'mode': ''}Passed
leading comma is not a pause{'ext': '', 'main': '5550115', 'mode': ''}{'ext': '', 'main': '5550115', 'mode': ''}Passed
seven-digit extension rejectedNoneNonePassed
six-digit extension acceptedNone{'ext': '123451', 'main': '5550115', 'mode': 'ext'}Failed

SHA-256 / 85e5882d4b7e5972a2791979a8ee13fb67f6078a4de51cb53edabcd6ee0d7ba9

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 11 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

Verification & scope

A deterministic toy contract over synthetic, obviously fictitious telephone numbers and toy country tables. The rules are stipulated for this model only and make no claim of conformance with any numbering plan or telecommunications standard. 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:52:23.077548+00:00.

Case digest / 380a1a21258c05943c4bff9a21244759fa8ef2652b1dbf150cab2ea52d8f6df9