You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Upload with every row rejected is shown as migrated (171 of 171 rows failed, no warning) #123
Found on 27 Oct 2026 while checking tracker item G20 on the dev machine. Relates to BR-34 (reconciliation) and #89 (persisted import counts).
What happened
Transactions (3).csv has 172 lines: a header and 171 data rows. It was uploaded at 02:01 AEDT on 27 Oct in dynamic mode (main at 9c8bc9b). The registry row in tenant_dev.csv_files shows:
row_count
total_rows
duplicate_rows_skipped
failed_rows
0
171
0
171
Every row was rejected, yet:
the file is listed under Migrated files as a normal entry, with 0 rows;
the header counts it in "2 files migrated";
nothing on the page says that 171 rows failed;
the reasons are lost. The upload response carried rowErrors, but they aren't stored, so the cause can't be found after the event.
The cause of the rejection is still being diagnosed: either the ragged-row rule (#88) or a type mismatch.
Why it matters
For a migration tool, a complete failure that looks like a success is the worst failure mode. A user can reasonably believe the data was migrated.
Proposed (to be confirmed)
When no row imports (failed_rows = total_rows > 0), treat the upload as failed:
don't register it as migrated;
drop the empty table;
return an error with the first row errors.
When some rows fail, keep the import, but show the failed count on the Migrated files row (for example "120 of 171 rows, 51 failed").
Keep the row errors (capped by MAX_ROW_ERRORS_REPORTED) with the import, so the reasons can be read later.
Done when
A file whose every row fails is reported as a failed upload, and isn't listed as migrated.
These checks were run on the dev machine against the original file. They printed column shapes only (9 = digit, a = letter), never data values.
Not ragged rows. All 171 rows have 10 cells, the same as the header.
Type mismatch between the browser and the API. Both Date and Processed On hold values shaped 99 aaa 99, such as "27 Oct 26".
The browser's inferCell (csv-table-hub-main/src/lib/csv-preview.ts) marks a value as a possible timestamptz when it contains a space or T followed by a digit and new Date() can parse it. new Date("27 Oct 26") returns 27 Oct 2026, so both columns are sent as timestamptz.
The API's cast_value (api/services/csv_parse.py) accepts only ISO values (datetime.fromisoformat), so it rejects the Date column in every row. All 171 rows fail on their first column.
Confirmed with Node: for "27 Oct 26", /[T ]\d/ is true and new Date(...) is valid.
Proposed fix (to be confirmed)
The browser infers date / timestamptz only for values the API accepts (ISO), so non-ISO dates import as text. Teaching the API to parse "27 Oct 26" isn't proposed: formats like 03/04/26 are ambiguous.
The handling proposed above: an upload where every row fails is a failed upload; partial failures show their count; row errors are kept.
Reopened under the closure rule: no issue closes without clean evidence attached.
PR #124 was merged on 27 Oct (443ed9a), with CI 3/3 on 45e78b8 and the local CI replica at 311/0/0. The "Done when" still needs the product owner's re-upload of Transactions (3).csv on the dev machine, with a screenshot showing 171 rows imported.
Activity
amar-python commentedon Oct 27, 2026
Root cause found (27 Oct, 18:40)
These checks were run on the dev machine against the original file. They printed column shapes only (
9= digit,a= letter), never data values.99 aaa 99, such as "27 Oct 26".inferCell(csv-table-hub-main/src/lib/csv-preview.ts) marks a value as a possibletimestamptzwhen it contains a space orTfollowed by a digit andnew Date()can parse it.new Date("27 Oct 26")returns 27 Oct 2026, so both columns are sent astimestamptz.cast_value(api/services/csv_parse.py) accepts only ISO values (datetime.fromisoformat), so it rejects the Date column in every row. All 171 rows fail on their first column./[T ]\d/is true andnew Date(...)is valid.Proposed fix (to be confirmed)
date/timestamptzonly for values the API accepts (ISO), so non-ISO dates import as text. Teaching the API to parse "27 Oct 26" isn't proposed: formats like 03/04/26 are ambiguous.Generated by Claude Code
Merge pull request #124 from amar-python/fix/123-failed-uploads
amar-python commentedon Oct 27, 2026
Reopened under the closure rule: no issue closes without clean evidence attached.
PR #124 was merged on 27 Oct (443ed9a), with CI 3/3 on 45e78b8 and the local CI replica at 311/0/0. The "Done when" still needs the product owner's re-upload of
Transactions (3).csvon the dev machine, with a screenshot showing 171 rows imported.Generated by Claude Code
amar-python commentedon Oct 27, 2026
Evidence for closure. The product owner re-uploaded the file on the dev machine on 27 Oct 2026, 19:33 AEDT, after PR #124 merged (443ed9a).
Transactions (3).csvwas overwritten: Imported 171 of 171 rows, and the Migrated files list shows 171 rows with no failed rows.total_rows171,failed_rows171).