FA-47531 / Delimited text / Open access
Empty physical TSV records vanish during framing · case 01
A structured table violates the declared record or column contract.
ROOT CAUSE
The framer treats an empty payload as absence of a record.
VERIFIED REPAIR
Preserve the named invariant at the faulty decision: rows.append(''.join(buf))
Unsuccessful approach: Whitespace filtering additionally loses space-only physical records.
Case contract
Frame raw TSV records from arbitrary string chunks using CRLF only. Bare CR and bare LF are invalid. A trailing nonterminated record is allowed; a final CR is invalid. Return records without terminators, retaining empty records.
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):
rows, buf, pending = [], [], False
for chunk in data:
for ch in chunk:
if pending:
if ch != '\n': return None
if buf: rows.append(''.join(buf))
buf, pending = [], False
elif ch == '\r': pending = True
elif ch == '\n': return None
else: buf.append(ch)
if pending: return None
if buf: rows.append(''.join(buf))
return rows
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('split terminator', solve(_vary(['@\r', '\nZ\r', '\n'])), _vary(['@', 'Z']))
check('whole', solve(_vary(['@\tA\r\nB'])), _vary(['@\tA', 'B']))
check('empty records', solve(_vary(['\r\n\r\n'])), _vary(['', '']))
check('empty chunks', solve(_vary(['', '@', '', '\r', '', '\n', ''])), _vary(['@']))
check('trailing CR', solve(_vary(['@\r'])), _vary(None))
check('bare LF', solve(_vary(['@\n'])), _vary(None))
check('bad CR', solve(_vary(['@\rZ'])), _vary(None))
check('no data', solve(_vary([])), _vary([]))
check('trailing unframed', solve(_vary(['@'])), _vary(['@']))
check('three chunks', solve(_vary(['@\r', '\n', 'X'])), _vary(['@', 'X']))
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 |
|---|---|---|---|
| split terminator | ['cell', 'Z'] | ['cell', 'Z'] | Passed |
| whole | ['cell\tA', 'B'] | ['cell\tA', 'B'] | Passed |
| empty records | [] | ['', ''] | Failed |
| empty chunks | ['cell'] | ['cell'] | Passed |
| trailing CR | None | None | Passed |
| bare LF | None | None | Passed |
| bad CR | None | None | Passed |
| no data | [] | [] | Passed |
| trailing unframed | ['cell'] | ['cell'] | Passed |
| three chunks | ['cell', 'X'] | ['cell', 'X'] | Passed |
SHA-256 / 293b2cc0497d96e288aa172bbab58e5f362426df9e671d1a9dd6eb27aae450c3
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):
rows, buf, pending = [], [], False
for chunk in data:
for ch in chunk:
if pending:
if ch != '\n': return None
if ''.join(buf).strip(): rows.append(''.join(buf))
buf, pending = [], False
elif ch == '\r': pending = True
elif ch == '\n': return None
else: buf.append(ch)
if pending: return None
if buf: rows.append(''.join(buf))
return rows
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('split terminator', solve(_vary(['@\r', '\nZ\r', '\n'])), _vary(['@', 'Z']))
check('whole', solve(_vary(['@\tA\r\nB'])), _vary(['@\tA', 'B']))
check('empty records', solve(_vary(['\r\n\r\n'])), _vary(['', '']))
check('empty chunks', solve(_vary(['', '@', '', '\r', '', '\n', ''])), _vary(['@']))
check('trailing CR', solve(_vary(['@\r'])), _vary(None))
check('bare LF', solve(_vary(['@\n'])), _vary(None))
check('bad CR', solve(_vary(['@\rZ'])), _vary(None))
check('no data', solve(_vary([])), _vary([]))
check('trailing unframed', solve(_vary(['@'])), _vary(['@']))
check('three chunks', solve(_vary(['@\r', '\n', 'X'])), _vary(['@', 'X']))
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 |
|---|---|---|---|
| split terminator | ['cell', 'Z'] | ['cell', 'Z'] | Passed |
| whole | ['cell\tA', 'B'] | ['cell\tA', 'B'] | Passed |
| empty records | [] | ['', ''] | Failed |
| empty chunks | ['cell'] | ['cell'] | Passed |
| trailing CR | None | None | Passed |
| bare LF | None | None | Passed |
| bad CR | None | None | Passed |
| no data | [] | [] | Passed |
| trailing unframed | ['cell'] | ['cell'] | Passed |
| three chunks | ['cell', 'X'] | ['cell', 'X'] | Passed |
SHA-256 / 9e3d69da9a181f88e3e310140463d7cbc2ffbd60ee713b391d0ebe1427d814e1
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):
rows, buf, pending = [], [], False
for chunk in data:
for ch in chunk:
if pending:
if ch != '\n': return None
rows.append(''.join(buf))
buf, pending = [], False
elif ch == '\r': pending = True
elif ch == '\n': return None
else: buf.append(ch)
if pending: return None
if buf: rows.append(''.join(buf))
return rows
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('split terminator', solve(_vary(['@\r', '\nZ\r', '\n'])), _vary(['@', 'Z']))
check('whole', solve(_vary(['@\tA\r\nB'])), _vary(['@\tA', 'B']))
check('empty records', solve(_vary(['\r\n\r\n'])), _vary(['', '']))
check('empty chunks', solve(_vary(['', '@', '', '\r', '', '\n', ''])), _vary(['@']))
check('trailing CR', solve(_vary(['@\r'])), _vary(None))
check('bare LF', solve(_vary(['@\n'])), _vary(None))
check('bad CR', solve(_vary(['@\rZ'])), _vary(None))
check('no data', solve(_vary([])), _vary([]))
check('trailing unframed', solve(_vary(['@'])), _vary(['@']))
check('three chunks', solve(_vary(['@\r', '\n', 'X'])), _vary(['@', 'X']))
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 |
|---|---|---|---|
| split terminator | ['cell', 'Z'] | ['cell', 'Z'] | Passed |
| whole | ['cell\tA', 'B'] | ['cell\tA', 'B'] | Passed |
| empty records | ['', ''] | ['', ''] | Passed |
| empty chunks | ['cell'] | ['cell'] | Passed |
| trailing CR | None | None | Passed |
| bare LF | None | None | Passed |
| bad CR | None | None | Passed |
| no data | [] | [] | Passed |
| trailing unframed | ['cell'] | ['cell'] | Passed |
| three chunks | ['cell', 'X'] | ['cell', 'X'] | Passed |
SHA-256 / f495bf941e395e1a4d39a9c3aa637de71fe7a5e1e9f5955fd1bc41eb65d05334
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:42.448314+00:00.
Case digest / 2758359f4ac4845ea83a72a57d3edef1f89897abcbdbcb16e802817ff825a630