Search the documentation

Find a page by title or section.

Troubleshooting

Imports

Rejected files, failed rows, silent updates and missing invitations — what each import outcome means and how to get the data in.

Updated

An import fails in one of two ways, and they are worth telling apart before you start editing a spreadsheet. Either the file was rejected and no row was read at all, or the file was accepted and individual rows failed. A file-level rejection shows one error message; a row-level failure shows a report with a status against each row.

Who can do this

Role
Administrators
Permission
imports:readimports:writedestinations:write

Running an import needs imports:write AND the permission for the entity you are importing — destinations:write, drivers:write, and so on. Browsing past runs, editing failed rows and retrying are gated separately behind the import_history feature.

Behind the import_history feature flag. Ask support to enable it for your organisation.

The file is rejected before any row is read

File-level rejections

Unsupported or undetectable file format
Cause

The format could not be resolved from the file type or the file extension.

Cooriroo accepts CSV, XLSX and JSON. The format is worked out from the upload’s declared type first and the filename extension second, so a spreadsheet saved with no extension, or renamed to something unexpected, is refused before anything is parsed. Re-save it with the right extension.

JSON has one extra rule worth knowing: the body must be an array of flat objects. Nested objects and arrays inside a field are refused with the field named, and trailing content after the array is refused rather than silently importing the first part.

invalid header: unknown columns
Cause

A column in your header does not match any importable column for that entity.

Column matching is case-insensitive and ignores surrounding spaces, but the names themselves are fixed. The error lists every unrecognised column at once, so you can fix them in one pass.

The safest cure is to press Download template in the import dialog and start from that file. The template is generated for your tenant, so it already includes your custom fields and your configured type values — which is exactly why a column that works for one tenant can be unknown in another.

invalid header: missing required columns, or duplicate columns
Cause

A required column is absent, or the same column appears twice.

Required columns must be present even when some rows leave them blank — a blank required cell fails that row, but a missing required column fails the whole file. Duplicates are rejected too, because the engine cannot tell which copy is authoritative.

All three problems are reported together in one message: unknown columns first, then duplicates, then missing required ones.

file exceeds the maximum of 500 rows, or the upload is too large
Cause

Imports run inside the request, so both the row count and the file size are capped.

A single import accepts at most 500 data rows and an upload of at most 10 MB. Split a larger file and run it in batches. There is no partial acceptance of an over-cap file — nothing is imported.

If you are close to the row cap, prefer Best effort mode. A 500-row all-or-nothing run discards every row for one bad cell, which is a long round trip.

file contains no data rows, or the header row is missing
Cause

The engine found no usable header, or no non-empty rows beneath it.

Completely empty rows are skipped rather than failed, so a file of blank rows reports as having no data. A header with an unnamed column is refused with the column position — usually a stray value in a cell to the right of your real header.

Comment lines at the top of a downloaded template are skipped automatically, so you can leave the field guide in place and re-import the template as-is.

Header rows, for reference

text
name,type,status,address_line_1,address_line_2,city,state,postal_code,country,latitude,longitude,contact_name,contact_phone,contact_email,operating_hours,window_open,window_close,driver_emails,notes

Required for destinations: name, address_line_1, city, country. Required for drivers: email, first_name, last_name. Your tenant’s custom fields are appended to both, so treat the downloaded template as authoritative rather than these lists.

Rows fail, or nothing is saved

Row-level outcomes

Every row is marked failed or skipped and nothing was created
Cause

The import ran in All or nothing mode and at least one row failed.

All or nothing is the default. One bad row rolls the whole batch back: the offending rows show as failed with their field errors, and every other row shows as skipped — meaning "valid, but discarded with the batch".

Fix the failed rows and re-run, or switch the mode to Best effort so the good rows land and only the bad ones are left behind.

Some rows were created and others were skipped, with no error on the skipped ones
Cause

Best effort processes rows in chunks; a failure inside a chunk is replayed row by row.

Best effort writes in batches for speed. When a row in a batch fails, that batch is rolled back and replayed one row at a time, so only the genuinely bad rows fail. A skipped row with no error is one that was valid but did not persist — re-run it and it will import.

Rows updated existing records instead of creating new ones
Cause

Imports upsert on a business key, not on a blank slate.

Destinations match on name within your tenant, and drivers match on email. A row whose key already exists updates that record rather than creating a duplicate — the row outcome says updated rather than created.

If you meant to create a second record, change the key. If a driver row failed with a duplicate-email conflict instead of updating, the address belongs to a user who is not a driver: an import will not convert an existing user into one.

Blank cells did not clear the stored value
Cause

An empty optional cell means "leave unchanged", by design.

This is a deliberate contract across every importer: a blank optional cell leaves the stored value alone on update and leaves the field unset on create. It exists so a partial spreadsheet can be used to update one column without wiping the rest of the record.

It also means an import cannot be used to empty a field. Clear it on the record itself instead.

A cell was rejected as the wrong type
Cause

A non-blank cell that cannot be parsed fails its row rather than being dropped.

The rules the cell parser applies, with the message keyed to the column:

  • Dates must be YYYY-MM-DD. Any other layout is rejected — silently dropping it would be worse.
  • Times such as delivery windows are HH:MM.
  • Latitude and longitude must be numbers in range, and you must supply both or neither. A half pair fails the row.
  • Enum columns list their accepted values in the message. Case does not matter — a title-cased spreadsheet value is accepted.
  • Multi-value cells such as driver emails or certifications are separated by a semicolon, because the comma is already the CSV delimiter.
  • Operating hours must be valid JSON.

After the import

Things that went in, but not as expected

Coordinates were not filled in from the address
Cause

Coordinate auto-fill is a separate entitlement, and it is best-effort even when on.

Auto-fill only runs when the geocoding auto-fill capability is enabled for your tenant, and only for rows that left both coordinate cells blank — a coordinate you supplied is never overwritten. Rows it did fill carry a warning on the outcome saying the coordinates were derived.

Even when enabled it can stop early. The whole enrichment pass has a time budget, and a provider rate limit stops it for the remaining rows. Those rows still import — just without coordinates. Re-importing the same file picks them up, because the earlier lookups are cached.

Imported drivers never received an invitation email
Cause

Invitations are sent only for rows the import actually kept, after every row has resolved.

Sending during the write would email people whose row was then rolled back, so invitations go out afterwards and only for drivers that were created — never for a driver row that updated an existing record, and never on a dry run.

If created drivers still have nothing, the problem is email delivery rather than the import. Invitation sending is best-effort: a failure is logged, not turned into an import error, so the rows are already saved and you can re-invite from the driver record.

Import History is empty, or the menu item is not there
Cause

Persisted run history is a separate capability and is off by default.

Without it, imports still run — you just get the result in the dialog and nothing is kept afterwards. With it, every run is recorded, including uploads that were rejected outright, so you can see later why a file bounced.

A run is also attributed to a tenant, so a platform-level session with no tenant selected records nothing.

A past run cannot be edited or retried
Cause

Only completed, non-dry runs with failed or skipped rows can be replayed.

Dry runs and rejected uploads are refused: neither wrote anything, so there is nothing to converge. Within a retryable run, only the failed and skipped rows can be edited in place and replayed — successful rows are left alone.

A retry re-reads your current column configuration rather than the one the run was made with. If a custom field has since been renamed or removed, that column is dropped from the replay and any newly required column is added, so the drift shows up as per-row errors you can fix instead of failing the whole retry.

Terminology

Your organisation can rename these. If your screens say something else, this is what they mean here.

Column names versus labels
Templates show your terminology in their titles and labels, but the column names themselves never change — import against the names.Rename it in Customization → Terminology
Custom fields
Each defined custom field becomes an extra template column, keyed by its field key rather than its display label.Rename it in Customization → Custom Fields