FAILURE MAP
← Case archive

FA-47481 / Delimited text / Open access

Text after a closing quote is silently discarded · case 01

A structured table violates the declared record or column contract.

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

ROOT CAUSE

The postquote state ignores forbidden suffix text.

VERIFIED REPAIR

Preserve the named invariant at the faulty decision: else: return None

Unsuccessful approach: Appending suffix text admits a malformed closing boundary.

Case contract

Lex one physical comma record. A quote opens only at field start; doubled quotes decode inside quoted fields; after a closing quote only comma or EOF is legal. CR/LF outside quoted fields reject. Return fields and quote-origin flags; a physical newline inside quoted text remains literal.

Why this case matters

Delimited interchange needs explicit framing, schema and field semantics at ingestion and emission boundaries.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
def _vary(value):
    if value == '@END': return 3 + 4*N
    if isinstance(value, str): return value.replace('@', 'cell' * N)
    if isinstance(value, list): return [_vary(x) for x in value]
    if isinstance(value, dict): return {_vary(k): _vary(v) for k,v in value.items()}
    return value
N = 1
observations = []
def solve(data):
    result, buf, state, origin = [], [], 'start', False
    for ch in data:
        if state == 'quoted':
            if ch == '"': state = 'closed'
            else: buf.append(ch)
        elif state == 'closed':
            if ch == '"':
                buf.append('"')
                state = 'quoted'
            elif ch == ',':
                result.append([''.join(buf), origin])
                buf, state, origin = [], 'start', False
            else: pass
        elif ch == ',':
            result.append([''.join(buf), origin])
            buf, state, origin = [], 'start', False
        elif ch == '"':
            if state != 'start': return None
            state, origin = 'quoted', True
        elif ch in '\r\n': return None
        else:
            buf.append(ch)
            state = 'bare'
    if state == 'quoted': return None
    result.append([''.join(buf), origin])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('quoted flags', solve(_vary('"@",a')), _vary([['@', True], ['a', False]]))
check('doubled', solve(_vary('"a""b"')), _vary([['a"b', True]]))
check('triple ending', solve(_vary('"@"""')), _vary([['@"', True]]))
check('empty quoted', solve(_vary('""')), _vary([['', True]]))
check('empty bare', solve(_vary('')), _vary([['', False]]))
check('suffix comma', solve(_vary('"@",')), _vary([['@', True], ['', False]]))
check('bare quote', solve(_vary('a"b')), _vary(None))
check('balanced quote suffix', solve(_vary('a"b"')), _vary(None))
check('junk closing', solve(_vary('"a"x')), _vary(None))
check('space closing', solve(_vary('"a" ')), _vary(None))
check('quoted newlines', solve(_vary('"a\nb"')), _vary([['a\nb', True]]))
check('quoted carriage return', solve(_vary('"a\rb"')), _vary([['a\rb', True]]))
check('unquoted newline', solve(_vary('a\nb')), _vary(None))
check('two quoted', solve(_vary('"a","b"')), _vary([['a', True], ['b', True]]))
check('unterminated', solve(_vary('"a')), _vary(None))
check('plain', solve(_vary('@,z')), _vary([['@', False], ['z', False]]))
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
quoted flags[['cell', True], ['a', False]][['cell', True], ['a', False]]Passed
doubled[['a"b', True]][['a"b', True]]Passed
triple ending[['cell"', True]][['cell"', True]]Passed
empty quoted[['', True]][['', True]]Passed
empty bare[['', False]][['', False]]Passed
suffix comma[['cell', True], ['', False]][['cell', True], ['', False]]Passed
bare quoteNoneNonePassed
balanced quote suffixNoneNonePassed
junk closing[['a', True]]NoneFailed
space closing[['a', True]]NoneFailed
quoted newlines[['a\nb', True]][['a\nb', True]]Passed
quoted carriage return[['a\rb', True]][['a\rb', True]]Passed
unquoted newlineNoneNonePassed
two quoted[['a', True], ['b', True]][['a', True], ['b', True]]Passed
unterminatedNoneNonePassed
plain[['cell', False], ['z', False]][['cell', False], ['z', False]]Passed

SHA-256 / 3d9b5b4fda5acb8ed8b80375320d194f072be9c586acf708267b1cf14be85902

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
def _vary(value):
    if value == '@END': return 3 + 4*N
    if isinstance(value, str): return value.replace('@', 'cell' * N)
    if isinstance(value, list): return [_vary(x) for x in value]
    if isinstance(value, dict): return {_vary(k): _vary(v) for k,v in value.items()}
    return value
N = 1
observations = []
def solve(data):
    result, buf, state, origin = [], [], 'start', False
    for ch in data:
        if state == 'quoted':
            if ch == '"': state = 'closed'
            else: buf.append(ch)
        elif state == 'closed':
            if ch == '"':
                buf.append('"')
                state = 'quoted'
            elif ch == ',':
                result.append([''.join(buf), origin])
                buf, state, origin = [], 'start', False
            else: buf.append(ch)
        elif ch == ',':
            result.append([''.join(buf), origin])
            buf, state, origin = [], 'start', False
        elif ch == '"':
            if state != 'start': return None
            state, origin = 'quoted', True
        elif ch in '\r\n': return None
        else:
            buf.append(ch)
            state = 'bare'
    if state == 'quoted': return None
    result.append([''.join(buf), origin])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('quoted flags', solve(_vary('"@",a')), _vary([['@', True], ['a', False]]))
check('doubled', solve(_vary('"a""b"')), _vary([['a"b', True]]))
check('triple ending', solve(_vary('"@"""')), _vary([['@"', True]]))
check('empty quoted', solve(_vary('""')), _vary([['', True]]))
check('empty bare', solve(_vary('')), _vary([['', False]]))
check('suffix comma', solve(_vary('"@",')), _vary([['@', True], ['', False]]))
check('bare quote', solve(_vary('a"b')), _vary(None))
check('balanced quote suffix', solve(_vary('a"b"')), _vary(None))
check('junk closing', solve(_vary('"a"x')), _vary(None))
check('space closing', solve(_vary('"a" ')), _vary(None))
check('quoted newlines', solve(_vary('"a\nb"')), _vary([['a\nb', True]]))
check('quoted carriage return', solve(_vary('"a\rb"')), _vary([['a\rb', True]]))
check('unquoted newline', solve(_vary('a\nb')), _vary(None))
check('two quoted', solve(_vary('"a","b"')), _vary([['a', True], ['b', True]]))
check('unterminated', solve(_vary('"a')), _vary(None))
check('plain', solve(_vary('@,z')), _vary([['@', False], ['z', False]]))
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
quoted flags[['cell', True], ['a', False]][['cell', True], ['a', False]]Passed
doubled[['a"b', True]][['a"b', True]]Passed
triple ending[['cell"', True]][['cell"', True]]Passed
empty quoted[['', True]][['', True]]Passed
empty bare[['', False]][['', False]]Passed
suffix comma[['cell', True], ['', False]][['cell', True], ['', False]]Passed
bare quoteNoneNonePassed
balanced quote suffixNoneNonePassed
junk closing[['ax', True]]NoneFailed
space closing[['a ', True]]NoneFailed
quoted newlines[['a\nb', True]][['a\nb', True]]Passed
quoted carriage return[['a\rb', True]][['a\rb', True]]Passed
unquoted newlineNoneNonePassed
two quoted[['a', True], ['b', True]][['a', True], ['b', True]]Passed
unterminatedNoneNonePassed
plain[['cell', False], ['z', False]][['cell', False], ['z', False]]Passed

SHA-256 / bc1f9ce89cbf02579843fddca9e4c9216ae92be694ab37ffae06a63863bf3394

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
def _vary(value):
    if value == '@END': return 3 + 4*N
    if isinstance(value, str): return value.replace('@', 'cell' * N)
    if isinstance(value, list): return [_vary(x) for x in value]
    if isinstance(value, dict): return {_vary(k): _vary(v) for k,v in value.items()}
    return value
N = 1
observations = []
def solve(data):
    result, buf, state, origin = [], [], 'start', False
    for ch in data:
        if state == 'quoted':
            if ch == '"': state = 'closed'
            else: buf.append(ch)
        elif state == 'closed':
            if ch == '"':
                buf.append('"')
                state = 'quoted'
            elif ch == ',':
                result.append([''.join(buf), origin])
                buf, state, origin = [], 'start', False
            else: return None
        elif ch == ',':
            result.append([''.join(buf), origin])
            buf, state, origin = [], 'start', False
        elif ch == '"':
            if state != 'start': return None
            state, origin = 'quoted', True
        elif ch in '\r\n': return None
        else:
            buf.append(ch)
            state = 'bare'
    if state == 'quoted': return None
    result.append([''.join(buf), origin])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('quoted flags', solve(_vary('"@",a')), _vary([['@', True], ['a', False]]))
check('doubled', solve(_vary('"a""b"')), _vary([['a"b', True]]))
check('triple ending', solve(_vary('"@"""')), _vary([['@"', True]]))
check('empty quoted', solve(_vary('""')), _vary([['', True]]))
check('empty bare', solve(_vary('')), _vary([['', False]]))
check('suffix comma', solve(_vary('"@",')), _vary([['@', True], ['', False]]))
check('bare quote', solve(_vary('a"b')), _vary(None))
check('balanced quote suffix', solve(_vary('a"b"')), _vary(None))
check('junk closing', solve(_vary('"a"x')), _vary(None))
check('space closing', solve(_vary('"a" ')), _vary(None))
check('quoted newlines', solve(_vary('"a\nb"')), _vary([['a\nb', True]]))
check('quoted carriage return', solve(_vary('"a\rb"')), _vary([['a\rb', True]]))
check('unquoted newline', solve(_vary('a\nb')), _vary(None))
check('two quoted', solve(_vary('"a","b"')), _vary([['a', True], ['b', True]]))
check('unterminated', solve(_vary('"a')), _vary(None))
check('plain', solve(_vary('@,z')), _vary([['@', False], ['z', False]]))
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
quoted flags[['cell', True], ['a', False]][['cell', True], ['a', False]]Passed
doubled[['a"b', True]][['a"b', True]]Passed
triple ending[['cell"', True]][['cell"', True]]Passed
empty quoted[['', True]][['', True]]Passed
empty bare[['', False]][['', False]]Passed
suffix comma[['cell', True], ['', False]][['cell', True], ['', False]]Passed
bare quoteNoneNonePassed
balanced quote suffixNoneNonePassed
junk closingNoneNonePassed
space closingNoneNonePassed
quoted newlines[['a\nb', True]][['a\nb', True]]Passed
quoted carriage return[['a\rb', True]][['a\rb', True]]Passed
unquoted newlineNoneNonePassed
two quoted[['a', True], ['b', True]][['a', True], ['b', True]]Passed
unterminatedNoneNonePassed
plain[['cell', False], ['z', False]][['cell', False], ['z', False]]Passed

SHA-256 / bac48864035b7b80055290c2dab4772ec827a8f19a1edf5dceabcc1205a99283

Verification & scope

Deterministic bounded in-memory model. No claim of complete CSV or external format conformance. 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:44:41.839564+00:00.

Case digest / 3abbe04366d9ee9a429f78010473cc012a8a8b5a7ddc3288cdd2395acfce087a