· 7 min read
Fix import errors where they happen
Spreadsheet imports usually fail with a list of row numbers. A better pattern: map, validate and repair inside the product before anything is posted.
Most spreadsheet imports fail the same way: you upload a file, the product prints a list of row numbers with errors, and the only way forward is to fix the file in Excel and upload it again. A better bulk import UX pattern keeps repair inside the product: upload once, map your own columns with the gaps shown on the field, then fix, filter and bulk-edit rows in a grid before anything is posted. That's the pattern I designed for Bulk Import in Tigg, an accounting product for businesses in Nepal.
I designed it; I didn't build it. The senior frontend engineer at BIC Technology built the whole frontend, and the backend team built the service behind it. The full story is in the Bulk Import case study. This post pulls out the pattern, because it applies to CSV import design in any B2B SaaS product, not only accounting.
Why do CSV imports fail with a list of row numbers?
Tigg's old importer worked like many others. You downloaded a template, pasted your data into it, uploaded it, and got a screen like 38 records validated, 4 records have errors, followed by lines such as "Row: 22 Warehouse not found". The buttons were Confirm Upload and Reupload New File.
The messages weren't the real problem. The file was the only place anything could be fixed: leave the product, find the row, guess what "not found" meant, save, re-upload, wait. Looked at closely, "bad import UX" had five separate causes:
| Cause | What it does to people | What the design needs |
|---|---|---|
| Fixed header contract | A sheet headed "Qty" or "Godown" fails, or has to be reworked first | Map their columns, with suggestions |
| Errors cut off from data | A list keyed by row number; the value is in another program | Put each error on its cell |
| No partial progress | Nothing survives between attempts | An import you can leave and resume |
| No repair tools | One wrong warehouse across 40 rows is 40 edits | Select, filter and change many rows at once |
| Hidden, settings-dependent rules | Required fields change per organisation; a template can't show that | Show what is required here, while mapping |
Better error copy fixes none of these. Moving the repair fixes most of them.
The data import UX pattern: map, validate, repair, post
I think of an import as a session with a lifecycle, not a file transfer: upload once (a template is offered, not required), map, validate on the cell, repair in a grid, then post whole documents.
Step 1: show the gap on the field during mapping
The mapping page has two panels, Mapped and Unmapped, each with a count. Beside each match sits a sample of the sheet's values, so people can check a match by content, not only by heading. On the first visit the matches are already suggested: a column called "Godown" lands on Warehouse Name without anyone typing.
Required fields that are still unmapped are amber. And people do press Next too early; that state is reached in real use.
This matters more when required fields aren't fixed. In Tigg, billing locations, warehouses and automatic product codes switch fields on and off per organisation. The same template can be complete for one business and incomplete for another, so the mapping page, not the template, has to say what is missing.
Step 2: put each error on its cell
Once mapping passes, the rows open in a full-width grid. Every cell has a type: text, number, date, or a searchable dropdown for customer, product or warehouse. Free text is where import errors come from; a typed editor prevents an error instead of reporting it.
A wrong value is tinted and carries its own message. This is one of the oldest error-message guidelines, and it's worth repeating: show the message close to the error's source.
Step 3: filter by error and fix many rows at once
Errors in imports repeat. If a distributor's sheet spells a warehouse "Main Godam" on eight rows, nobody should edit eight cells. The design has one control that counts and filters at once (Total rows, Valid, Errors), a filter for "errors in this column", and a bulk edit bar that states its scope first: Bulk edit (8 rows): column, value, Apply.
Step 4: post documents, not rows
A delivery note with three items is three lines in the sheet but one document in the books. In the build, the senior frontend engineer made posting stop if only some rows of a document are selected, and name that document. Half a document in the books is worse than none. Posting also asks for confirmation, because it "will create actual transactions and cannot be undone".
How do other import tools handle errors? A 2026 comparison
I compared the pattern with other products in September 2026, after the design, from public help-centre documentation only. I didn't use any of them hands-on, and a feature missing below may exist without public documentation. This is not what I studied at the time.
| Product | Mapping | Fixing errors |
|---|---|---|
| Zoho Inventory | Auto-mapped, with an option to save the selections for future imports | A preview counts ready, skipped and unmapped records; fix the file and re-import |
| QuickBooks Online | A dropdown per field | Invalid cells are highlighted in red in the review and corrected there; 1,000 rows at a time; an import can't be undone |
| Odoo 19 | Suggested automatically, with a manual override | A Test step checks the data before the real import |
| TallyPrime | Mapping templates | An exceptions report to identify and correct issues before completing |
| Flatfile (import tool) | Suggested matches | Edit any cell; red errors and yellow warnings; filter by error; find and replace, including empty values |
Mapping is standard. In-product repair is still rare in accounting software; it mostly lives in dedicated import tools. The comparison also showed me two things the design doesn't do yet: remembered mappings for repeat imports (Zoho saves selections; Tally has templates), and a warning level separate from errors, so a note like "this category will be created" doesn't read as a failure.
What the engineer decided, and why credit matters
Several of the best behaviours in the built importer weren't in my frames. The senior frontend engineer decided them:
- work in the grid is saved as a draft, and an unfinished import can be resumed from Recent imports;
- a cell is checked when you leave it, not on every keystroke, and its error clears as soon as you change it;
- limits are stated at upload, and a column with data but no heading is rejected with a message instead of being dropped silently.
A design-only case that takes credit for build decisions isn't honest. It also taught me that a handoff has to carry behaviour, not only looks. Arrow-key movement and pasting a block of values weren't in my frames, and they aren't in the build yet. Next time I'd add a short interaction spec: a keyboard map, and what Enter and Tab do. I write more about handoff in being the only designer on a product team.
A checklist for error recovery in import UX
- Accept people's own column names and suggest matches, with sample values.
- Say what is required for this account, on the mapping page.
- Block early, on the field, and name what's missing.
- Put every error on its cell, with a visible marker, not colour alone.
- Use typed editors so wrong values can't be typed in the first place.
- Count and filter by error, per column.
- Let one value fix many selected rows, and state the scope first.
- Save progress; let people leave and resume.
- Post whole documents, and confirm anything irreversible.
- Give empty, rejected-file and interrupted states their own wording (see my state checklist for business software).
What shipped, and what isn't measured
The design was handed off, marked ready for development, before the build began on 2 June 2026. Delivery Note and Goods Received Note import reached a tagged release in July 2026, and Inventory Adjustment import followed in August, all on the same mapping and repair pages. Product/Service import was on UAT in September.
Measured outcome: none. I have no import counts, success rates or time-to-import figures. If I could measure one thing first, it would be whether the round trip is really gone: the same file uploaded again within a day. So the claim is narrow. Supported errors (typed values, references, required cells, repeated fixes) are repaired inside the product before posting. Some problems still start in the file, and how I label claims like this is the subject of writing honest case studies.
References
- Intuit, Import products and services into QuickBooks Online.
- Flatfile, Importing Data with Flatfile: Overview.
- Zoho, Import Data, Zoho Inventory user guide.
- Odoo, Export and import data, Odoo 19.0 documentation.
- Tally Solutions, Import data in TallyPrime.
- Tim Neusesser and Evan Sunwall, Error-Message Guidelines, Nielsen Norman Group.
All vendor pages were read in September and October 2026.
questions people ask
Frequently asked questions
What is the best UX pattern for bulk CSV or Excel import errors?
Show each error on the cell that caused it, inside the product, and let people fix it there with typed editors, filters and bulk edits. Re-uploading a corrected file should be the exception, not the only way forward.
Should an importer block on unmapped required fields or flag every row?
Block at the mapping step and name the missing fields on the field itself. One missing mapping is one fix; flagging it on every row turns it into dozens of identical errors.
Do accounting products let you fix import errors in a grid?
In a 2026 reading of public help documentation, most accounting suites map columns and then send you back to the file. QuickBooks Online documents fixing invalid cells in its review grid, and dedicated import tools such as Flatfile document filtering by error and bulk fixes.
Who built Tigg's Bulk Import?
Bibhushan Saakha designed it as Tigg's only UI/UX designer. The senior frontend engineer built the whole frontend, and the backend team built the service behind it.