FA-196 / Serialization / Open access
Line splitting removes a quoted CSV line break · case 01
A quoted multiline field is either split into records or silently concatenated without its newline.
ROOT CAUSE
Physical line splitting happens before a CSV-aware reader can preserve quoted line breaks.
VERIFIED REPAIR
Give the CSV parser the original text stream with newline translation disabled.
Unsuccessful approach: Using a CSV reader after splitlines understands quotes but has already discarded the embedded line endings.
Case contract
Read comma-delimited CSV using double-quote escaping and strict parser mode. Preserve embedded CR/LF characters within quoted fields, empty fields, and blank records; return None for parser errors.
Why this case matters
CSV records can span physical lines. Correct quote handling is not enough if the input preparation already removed information.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import csv
import io
N = 1
observations = []
def solve(text):
return [line.split(',') for line in text.splitlines()]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
value = 'row' * N
check('embedded LF preserved', solve('"' + value + '\nnext",z\r\n'), [[value + '\nnext', 'z']])
check('embedded CRLF preserved', solve('"a\r\nb",' + str(N) + '\r\n'), [['a\r\nb', str(N)]])
check('quoted comma is field content', solve('"a,b",c\n'), [['a,b', 'c']])
check('doubled quote decoded', solve('"a""b",c\n'), [['a"b', 'c']])
check('trailing empty field', solve(value + ',\n'), [[value, '']])
check('blank records stay blank records', solve('\n' + value + '\n'), [[], [value]])
check('empty input', solve(''), [])
check('unterminated quoted field rejected', solve('"open,' + value), None)
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 |
|---|---|---|---|
| embedded LF preserved | [['"row'], ['next"', 'z']] | [['row\nnext', 'z']] | Failed |
| embedded CRLF preserved | [['"a'], ['b"', '1']] | [['a\r\nb', '1']] | Failed |
| quoted comma is field content | [['"a', 'b"', 'c']] | [['a,b', 'c']] | Failed |
| doubled quote decoded | [['"a""b"', 'c']] | [['a"b', 'c']] | Failed |
| trailing empty field | [['row', '']] | [['row', '']] | Passed |
| blank records stay blank records | [[''], ['row']] | [[], ['row']] | Failed |
| empty input | [] | [] | Passed |
| unterminated quoted field rejected | [['"open', 'row']] | None | Failed |
SHA-256 / d1ba522b69225e593ddbae8dbf92ca23a588432f2c30d622f7cb515956e532e4
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import csv
import io
N = 1
observations = []
def solve(text):
try:
return list(csv.reader(text.splitlines(), strict=True))
except csv.Error:
return None
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
value = 'row' * N
check('embedded LF preserved', solve('"' + value + '\nnext",z\r\n'), [[value + '\nnext', 'z']])
check('embedded CRLF preserved', solve('"a\r\nb",' + str(N) + '\r\n'), [['a\r\nb', str(N)]])
check('quoted comma is field content', solve('"a,b",c\n'), [['a,b', 'c']])
check('doubled quote decoded', solve('"a""b",c\n'), [['a"b', 'c']])
check('trailing empty field', solve(value + ',\n'), [[value, '']])
check('blank records stay blank records', solve('\n' + value + '\n'), [[], [value]])
check('empty input', solve(''), [])
check('unterminated quoted field rejected', solve('"open,' + value), None)
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 |
|---|---|---|---|
| embedded LF preserved | [['rownext', 'z']] | [['row\nnext', 'z']] | Failed |
| embedded CRLF preserved | [['ab', '1']] | [['a\r\nb', '1']] | Failed |
| quoted comma is field content | [['a,b', 'c']] | [['a,b', 'c']] | Passed |
| doubled quote decoded | [['a"b', 'c']] | [['a"b', 'c']] | Passed |
| trailing empty field | [['row', '']] | [['row', '']] | Passed |
| blank records stay blank records | [[], ['row']] | [[], ['row']] | Passed |
| empty input | [] | [] | Passed |
| unterminated quoted field rejected | None | None | Passed |
SHA-256 / ab4a610ee411cb9183709092eb5c8220a4cf109ccd5688ab73defee611c7e066
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import csv
import io
N = 1
observations = []
def solve(text):
try:
return list(csv.reader(io.StringIO(text, newline=''), strict=True))
except csv.Error:
return None
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
value = 'row' * N
check('embedded LF preserved', solve('"' + value + '\nnext",z\r\n'), [[value + '\nnext', 'z']])
check('embedded CRLF preserved', solve('"a\r\nb",' + str(N) + '\r\n'), [['a\r\nb', str(N)]])
check('quoted comma is field content', solve('"a,b",c\n'), [['a,b', 'c']])
check('doubled quote decoded', solve('"a""b",c\n'), [['a"b', 'c']])
check('trailing empty field', solve(value + ',\n'), [[value, '']])
check('blank records stay blank records', solve('\n' + value + '\n'), [[], [value]])
check('empty input', solve(''), [])
check('unterminated quoted field rejected', solve('"open,' + value), None)
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 |
|---|---|---|---|
| embedded LF preserved | [['row\nnext', 'z']] | [['row\nnext', 'z']] | Passed |
| embedded CRLF preserved | [['a\r\nb', '1']] | [['a\r\nb', '1']] | Passed |
| quoted comma is field content | [['a,b', 'c']] | [['a,b', 'c']] | Passed |
| doubled quote decoded | [['a"b', 'c']] | [['a"b', 'c']] | Passed |
| trailing empty field | [['row', '']] | [['row', '']] | Passed |
| blank records stay blank records | [[], ['row']] | [[], ['row']] | Passed |
| empty input | [] | [] | Passed |
| unterminated quoted field rejected | None | None | Passed |
SHA-256 / 49ccf1e81b6e55e27b51bc9c38d506a8539a44beedcd6df811d71adbb34646f4
Verification & scope
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:36:51.028600+00:00.
Case digest / 27b2330995e058685c30369b02e95a5dfb0823bb85e745da7aae54f3c39dd4ab