FAILURE MAP
← Case archive

FA-44896 / Data systems / Open access

Pivot drops null fact values inside a cell · case 01

Pivot drops null fact values inside a cell.

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

ROOT CAUSE

categorical-pivot-lists: Pivot drops null fact values inside a cell.

VERIFIED REPAIR

Preserve the stated physical representation and operation order: Pivot [row-id,category,value] into [row-id,list-for-category...] using the caller category order. Each cell is an ordered bag list. Unknown categories do not populate cells but retain their row identity; absent cells are empty lists and null values remain elements.

Unsuccessful approach: Zero imputation changes null-valued facts.

Case contract

Pivot [row-id,category,value] into [row-id,list-for-category...] using the caller category order. Each cell is an ordered bag list. Unknown categories do not populate cells but retain their row identity; absent cells are empty lists and null values remain elements.

Why this case matters

A bounded deterministic data engine model makes representation and changelog faults reproducible.

1 / The failure

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

N = 1
observations = []
def solve(d):
    try:
        rows,categories=d
        ids=list(dict.fromkeys(row[0] for row in rows))
        out=[]
        for ident in ids:
            record=[ident]
            for category in categories:
                cell=[value for i,c,value in rows if i==ident and c==category]
                record.append([v for v in cell if v is not None])
            out.append(record)
        return out
    except (IndexError, KeyError, ValueError, StopIteration) as exc:
        return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('column order', solve([[[1, 'a', 1], [1, 'b', 2]], ['b', 'a']]), [[1, [2], [1]]])
    check('unknown-only row', solve([[[1, 'z', 1]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 1], [2, 'a', 2]], ['a']]), [[1, [1]], [2, [2]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 1], [1, 'a', 1]], ['a']]), [[1, [1, 1]]])
    check('no categories', solve([[[1, 'a', 1]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 2:
    check('column order', solve([[[1, 'a', 2], [1, 'b', 3]], ['b', 'a']]), [[1, [3], [2]]])
    check('unknown-only row', solve([[[1, 'z', 2]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 2], [2, 'a', 3]], ['a']]), [[1, [2]], [2, [3]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 2], [1, 'a', 2]], ['a']]), [[1, [2, 2]]])
    check('no categories', solve([[[1, 'a', 2]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 3:
    check('column order', solve([[[1, 'a', 3], [1, 'b', 4]], ['b', 'a']]), [[1, [4], [3]]])
    check('unknown-only row', solve([[[1, 'z', 3]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 3], [2, 'a', 4]], ['a']]), [[1, [3]], [2, [4]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 3], [1, 'a', 3]], ['a']]), [[1, [3, 3]]])
    check('no categories', solve([[[1, 'a', 3]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 4:
    check('column order', solve([[[1, 'a', 4], [1, 'b', 5]], ['b', 'a']]), [[1, [5], [4]]])
    check('unknown-only row', solve([[[1, 'z', 4]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 4], [2, 'a', 5]], ['a']]), [[1, [4]], [2, [5]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 4], [1, 'a', 4]], ['a']]), [[1, [4, 4]]])
    check('no categories', solve([[[1, 'a', 4]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 5:
    check('column order', solve([[[1, 'a', 5], [1, 'b', 6]], ['b', 'a']]), [[1, [6], [5]]])
    check('unknown-only row', solve([[[1, 'z', 5]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 5], [2, 'a', 6]], ['a']]), [[1, [5]], [2, [6]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 5], [1, 'a', 5]], ['a']]), [[1, [5, 5]]])
    check('no categories', solve([[[1, 'a', 5]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
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
column order[[1, [2], [1]]][[1, [2], [1]]]Passed
unknown-only row[[1, []]][[1, []]]Passed
two row groups[[1, [1]], [2, [2]]][[1, [1]], [2, [2]]]Passed
null fact[[1, []]][[1, [None]]]Failed
duplicate fact[[1, [1, 1]]][[1, [1, 1]]]Passed
no categories[[1]][[1]]Passed
no facts[][]Passed

SHA-256 / 2b40e693131466ce716cc3c362c3658b3edd4bb8b81232be1127e90af8011fb6

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(d):
    try:
        rows,categories=d
        ids=list(dict.fromkeys(row[0] for row in rows))
        out=[]
        for ident in ids:
            record=[ident]
            for category in categories:
                cell=[value for i,c,value in rows if i==ident and c==category]
                record.append([0 if v is None else v for v in cell])
            out.append(record)
        return out
    except (IndexError, KeyError, ValueError, StopIteration) as exc:
        return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('column order', solve([[[1, 'a', 1], [1, 'b', 2]], ['b', 'a']]), [[1, [2], [1]]])
    check('unknown-only row', solve([[[1, 'z', 1]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 1], [2, 'a', 2]], ['a']]), [[1, [1]], [2, [2]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 1], [1, 'a', 1]], ['a']]), [[1, [1, 1]]])
    check('no categories', solve([[[1, 'a', 1]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 2:
    check('column order', solve([[[1, 'a', 2], [1, 'b', 3]], ['b', 'a']]), [[1, [3], [2]]])
    check('unknown-only row', solve([[[1, 'z', 2]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 2], [2, 'a', 3]], ['a']]), [[1, [2]], [2, [3]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 2], [1, 'a', 2]], ['a']]), [[1, [2, 2]]])
    check('no categories', solve([[[1, 'a', 2]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 3:
    check('column order', solve([[[1, 'a', 3], [1, 'b', 4]], ['b', 'a']]), [[1, [4], [3]]])
    check('unknown-only row', solve([[[1, 'z', 3]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 3], [2, 'a', 4]], ['a']]), [[1, [3]], [2, [4]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 3], [1, 'a', 3]], ['a']]), [[1, [3, 3]]])
    check('no categories', solve([[[1, 'a', 3]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 4:
    check('column order', solve([[[1, 'a', 4], [1, 'b', 5]], ['b', 'a']]), [[1, [5], [4]]])
    check('unknown-only row', solve([[[1, 'z', 4]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 4], [2, 'a', 5]], ['a']]), [[1, [4]], [2, [5]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 4], [1, 'a', 4]], ['a']]), [[1, [4, 4]]])
    check('no categories', solve([[[1, 'a', 4]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 5:
    check('column order', solve([[[1, 'a', 5], [1, 'b', 6]], ['b', 'a']]), [[1, [6], [5]]])
    check('unknown-only row', solve([[[1, 'z', 5]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 5], [2, 'a', 6]], ['a']]), [[1, [5]], [2, [6]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 5], [1, 'a', 5]], ['a']]), [[1, [5, 5]]])
    check('no categories', solve([[[1, 'a', 5]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
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
column order[[1, [2], [1]]][[1, [2], [1]]]Passed
unknown-only row[[1, []]][[1, []]]Passed
two row groups[[1, [1]], [2, [2]]][[1, [1]], [2, [2]]]Passed
null fact[[1, [0]]][[1, [None]]]Failed
duplicate fact[[1, [1, 1]]][[1, [1, 1]]]Passed
no categories[[1]][[1]]Passed
no facts[][]Passed

SHA-256 / bf561b0aed9229505b660adadd8b20eec84db57b631e969263b6a3488310168d

3 / The verified repair

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

N = 1
observations = []
def solve(d):
    try:
        rows,categories=d
        ids=list(dict.fromkeys(row[0] for row in rows))
        out=[]
        for ident in ids:
            record=[ident]
            for category in categories:
                cell=[value for i,c,value in rows if i==ident and c==category]
                record.append(cell)
            out.append(record)
        return out
    except (IndexError, KeyError, ValueError, StopIteration) as exc:
        return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
    check('column order', solve([[[1, 'a', 1], [1, 'b', 2]], ['b', 'a']]), [[1, [2], [1]]])
    check('unknown-only row', solve([[[1, 'z', 1]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 1], [2, 'a', 2]], ['a']]), [[1, [1]], [2, [2]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 1], [1, 'a', 1]], ['a']]), [[1, [1, 1]]])
    check('no categories', solve([[[1, 'a', 1]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 2:
    check('column order', solve([[[1, 'a', 2], [1, 'b', 3]], ['b', 'a']]), [[1, [3], [2]]])
    check('unknown-only row', solve([[[1, 'z', 2]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 2], [2, 'a', 3]], ['a']]), [[1, [2]], [2, [3]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 2], [1, 'a', 2]], ['a']]), [[1, [2, 2]]])
    check('no categories', solve([[[1, 'a', 2]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 3:
    check('column order', solve([[[1, 'a', 3], [1, 'b', 4]], ['b', 'a']]), [[1, [4], [3]]])
    check('unknown-only row', solve([[[1, 'z', 3]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 3], [2, 'a', 4]], ['a']]), [[1, [3]], [2, [4]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 3], [1, 'a', 3]], ['a']]), [[1, [3, 3]]])
    check('no categories', solve([[[1, 'a', 3]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 4:
    check('column order', solve([[[1, 'a', 4], [1, 'b', 5]], ['b', 'a']]), [[1, [5], [4]]])
    check('unknown-only row', solve([[[1, 'z', 4]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 4], [2, 'a', 5]], ['a']]), [[1, [4]], [2, [5]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 4], [1, 'a', 4]], ['a']]), [[1, [4, 4]]])
    check('no categories', solve([[[1, 'a', 4]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
elif N == 5:
    check('column order', solve([[[1, 'a', 5], [1, 'b', 6]], ['b', 'a']]), [[1, [6], [5]]])
    check('unknown-only row', solve([[[1, 'z', 5]], ['a']]), [[1, []]])
    check('two row groups', solve([[[1, 'a', 5], [2, 'a', 6]], ['a']]), [[1, [5]], [2, [6]]])
    check('null fact', solve([[[1, 'a', None]], ['a']]), [[1, [None]]])
    check('duplicate fact', solve([[[1, 'a', 5], [1, 'a', 5]], ['a']]), [[1, [5, 5]]])
    check('no categories', solve([[[1, 'a', 5]], []]), [[1]])
    check('no facts', solve([[], ['a']]), [])
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
column order[[1, [2], [1]]][[1, [2], [1]]]Passed
unknown-only row[[1, []]][[1, []]]Passed
two row groups[[1, [1]], [2, [2]]][[1, [1]], [2, [2]]]Passed
null fact[[1, [None]]][[1, [None]]]Passed
duplicate fact[[1, [1, 1]]][[1, [1, 1]]]Passed
no categories[[1]][[1]]Passed
no facts[][]Passed

SHA-256 / 2321267ab165b73e3dfda40a3391dbb8b81872432dbbb2c0dec96f9a9147cab9

Verification & scope

Offline stipulated semantics over valid small inputs; no performance, concurrency, or production-engine conformance claim. 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:16.654275+00:00.

Case digest / b3fc8e39102aa8d99ac1f0843666ca55d59fb95e15a68724ac1e90741a2b9fe9