The Spreadsheet That Ran Out of Rows — Python Bug Hunt
Modelled on Public Health England's October 2020 reporting failure: nearly 16,000 positive COVID-19 test results were left out of the daily figures, and…
- Language: Python
- Layer: Database
- Difficulty: Medium
- Concepts: Limits, Validation
- Modelled on: Public Health England · 2020
- Visible tests: a small file fits one sheet; 70,000 records are all exported
- Reward: 50 XP for a complete fix
Briefing
Modelled on Public Health England's October 2020 reporting failure: nearly 16,000 positive COVID-19 test results were left out of the daily figures, and their contacts were not traced, for about a week. Lab results arrived as CSV files and were loaded into Excel templates in the legacy XLS format, which holds at most 65,536 rows per sheet; everything past the limit was silently dropped.
exporter.py turns records into legacy sheets. It stops at the row limit without a word.
Fix export_sheets so every record is exported, split across as many sheets as it takes.
Bug report
BUG-XLSROWS · Priority: Critical (data loss) · Reported by: data pipeline
export_sheets(records, max_rows=None) — max_rows defaults to limits.XLS_MAX_ROWS (65,536):
- returns a list of sheets; every sheet is [limits.HEADER] followed by up to max_rows - 1 records, so no sheet has more than max_rows rows
- every record appears exactly once, in the original order; sheets are filled completely before the next one starts
- no records -> [[HEADER]]
- max_rows < 2 cannot hold a record: raise ValueError
Observed: a 70,000-row lab file produced one full sheet; 4,465 results were never uploaded, with no error.
Logs
[ingest] lab_feed_2020-10-01.csv: 70000 rows
[export] wrote results.xls (65536 rows)
[upload] 65535 results uploadedThe code as shipped
src/pipeline/exporter.py (editable)
limits = bug_require("./limits.py")
def export_sheets(records, max_rows=None):
if max_rows is None:
max_rows = limits.XLS_MAX_ROWS
sheet = [limits.HEADER]
for record in records:
if len(sheet) >= max_rows:
break
sheet.append(record)
return [sheet]
Read-only context: src/pipeline/limits.py.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More Python bug hunts.