# CAIRO-4118 — Import CSV Modal: Error Handling, Validation & Edge Cases

**Ticket:** [CAIRO-4118](https://wix.atlassian.net/browse/CAIRO-4118) · Status: In Progress · Priority: High
**Area:** `packages/cairo/src/components/ImportButton`, `packages/core/src/state/ImportState`

This tracker turns the ticket's task spec into individually-trackable items. All rows start `open`; flip to `done` / `dismiss` as resolved and record what was actually done (commit SHA, test name, rationale).

## General

| # | Task | Desired behavior | Status | Resolution / Notes |
|---|---|---|---|---|
| G1 | Success toast | On successful import, show a success toast | open | — |

## Step 1 — Upload: File-Level Failures

| # | Failure | Desired behavior | Status | Resolution / Notes |
|---|---|---|---|---|
| 1.1 | File can't be read | Toast: *"Couldn't read this file. Check your internet connection and that the file hasn't been moved or deleted."* + **"Try Again"** action | done | `ImportState.onFileSelected` now shows an ERROR toast (key `cairo.import.fileReadFailed`) with a **Try Again** action (`cairo.import.tryAgain`) that re-runs `onFileSelected(file)` on the `file.text()` read failure, instead of the inline parse-error text. Tests: *"shows a try-again toast and stays on upload step when the file cannot be read"*, *"retries reading the file when the toast try-again action is clicked"* in `Table.importButton.spec.tsx`. New key must be registered in the Translation Center (core `messages_en.json` is gitignored). |
| 1.2 | Malformed CSV (parse error) | Toast: *"Couldn't process this file. Make sure it's a comma-separated CSV file."* | done | `ImportState.onFileSelected` now fires an ERROR toast (key `cairo.import.processFailed`) on a Papa parse error and stays on the upload step, instead of the inline `parseError` text. Removed the now-dead `parseError` observable, the inline `import-upload-error` UI in `ImportStepUpload.tsx`, and the `getUploadError`/`uploadErrorExists` driver methods. Test: *"shows an error toast and stays on upload step for a malformed CSV"* in `Table.importButton.spec.tsx`. New key must be registered in the Translation Center (core `messages_en.json` is gitignored). |
| 1.3 | Non-UTF-8 encoding | Toast: *"Couldn't process this file due to its encoding. Make sure it's saved with UTF-8 encoding."* | done | `onFileSelected` reads raw bytes (`file.arrayBuffer()`) and decodes via `new TextDecoder('utf-8', { fatal: true })`, which throws on invalid UTF-8 — validating encoding against the bytes *before* decoding (the earlier U+FFFD-string heuristic was lossy / produced false positives; see PR #5468 review). A decode failure → ERROR toast (key `cairo.import.encodingFailed`) via `_rejectFile`, staying on upload step. `parseCsv` is now string-only. Test env polyfills `TextEncoder`/`TextDecoder` in `__tests__/spec-setup.ts`. Test: *"shows an encoding error toast and stays on upload step for a non-UTF-8 file"*. New key must be registered in the Translation Center (core `messages_en.json` is gitignored). |
| ~~1.4~~ | ~~File too large / too many rows~~ | ~~Deferred until API size limit is known~~ | dismiss | Deferred in ticket (struck through) |

## Step 2 — Configuration: Validations

| # | Case | Desired behavior | Status | Resolution / Notes |
|---|---|---|---|---|
| 2.1 | Duplicate field mapping | Once a collection field is selected in one dropdown, **disable** it (visible but unselectable) in all other dropdowns | open | — |
| 2.2 | Zero data rows | Show an **inline warning notice** inside step 2 (non-blocking) — user can still proceed or go back. [Design](https://www.figma.com/design/RpB9iQ6a43xcvKiovmJaA1/Import?node-id=72-39072) | open | — |
| 2.3 | Mismatch between CSV data and chosen field | Dropdown enters **error state** with a status message | open | — |

## Step 3 — Progress: Full Import Failures

| # | Failure | Desired behavior | Status | Resolution / Notes |
|---|---|---|---|---|
| 3.1 | Backup fails (pre-upload backup throws) | Put modal into **error state**; replace progress label with error message; footer CTA → **"Try again"** (re-runs import). [Design](https://www.figma.com/design/RpB9iQ6a43xcvKiovmJaA1/Import?node-id=145-12691) | open | — |
| 3.2 | Full batch failure (network/server error on first batch) | Modal in **error state** with message and **try again** action | open | — |
| 3.3 | Partial success (some batches succeed, then one throws) | Close modal; show toast with how many failed / succeeded + action to **download the CSV** | open | — |

## Status summary

| # | Topic | Status |
|---|---|---|
| G1 | Success toast | open |
| 1.1 | File can't be read | done |
| 1.2 | Malformed CSV | done |
| 1.3 | Non-UTF-8 encoding | done |
| 1.4 | File too large | dismiss (deferred) |
| 2.1 | Duplicate field mapping | open |
| 2.2 | Zero data rows | open |
| 2.3 | Field/data mismatch | open |
| 3.1 | Backup fails | open |
| 3.2 | Full batch failure | open |
| 3.3 | Partial success | open |
