Skip to content

Upload with every row rejected is shown as migrated (171 of 171 rows failed, no warning) #123

Closed

Description

@amar-python

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)

  1. 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.
  2. 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").
  3. 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.
  • A partly failed file shows its failed count.
  • Integration and vitest tests cover both.
  • A screenshot is attached here.

Generated by Claude Code

Activity

  1. amar-python commented on Oct 27, 2026

    @amar-python
    OwnerAuthor

    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.

    • 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)

    1. 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.
    2. The handling proposed above: an upload where every row fails is a failed upload; partial failures show their count; row errors are kept.

    Generated by Claude Code

  2. added a commit that references this issue on Oct 27, 2026
  3. amar-python commented on Oct 27, 2026

    @amar-python
    OwnerAuthor

    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.


    Generated by Claude Code

  4. amar-python commented on Oct 27, 2026

    @amar-python
    OwnerAuthor

    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).csv was overwritten: Imported 171 of 171 rows, and the Migrated files list shows 171 rows with no failed rows.
    • Before the fix, the same file gave 0 imported and 171 failed (registry total_rows 171, failed_rows 171).
    • With the fix, Date and Processed On ("27 Oct 26") are typed as text, so nothing is rejected.
    Image
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions