“Invalid CSV header: missing headers”, and the columns that vanish quietly

Invalid CSV header: missing headers

Shopify matches columns by header text. A header it does not recognise is not an error — the column is simply dropped, and nothing in the import report mentions it.

Check your file in the converterRuns in this browser. Nothing is uploaded, and the check happens before you download.

Why Shopify raises it

Shopify’s solutions to common product CSV import problems lists Invalid CSV header: missing headers and then prints the header row it expects, adding: “Remember to check for extra white spaces at the end of the first line.” A trailing space is enough.

The same page describes the softer failure, which is far more common: “I tried to upload my CSV and a Choose column headings window appeared” — “This window displays when the headers of your CSV file are incorrect.” Shopify is asking you to match the columns by hand because it could not.

What makes this error class dangerous is how little Shopify requires. Its product CSV reference says that to create new products “the only required column is Title” (plus URL handle if you are adding variants). So a file whose price column is misnamed imports perfectly — at 0.00. A file whose Title column is misnamed has no titles at all, and every line is skipped as “Ignored line #-## because it did not contain product data”.

The reference also warns about a dependency that catches people removing columns to tidy up: if you omit Option1 name and Option1 value when updating, “a new default variant is created and existing variants are deleted”.

How to find it in your CSV

Compare your header row against the real column names, character by character. The failures are mundane and all look fine at a glance:

  • Trailing or leading whitespace — "Title ". Invisible, and Shopify’s own help page calls it out.
  • Case and spacing differences — variant price for Variant Price, or Compare at price for Compare-at price with its hyphen.
  • Old column names. Shopify renamed much of the template and notes that it “maintains backward compatibility with older column names” — so Body (HTML) and Description, or Variant Grams and Weight value (grams), both work, which means two files can look completely different and both be right.
  • A BOM on the first header. A UTF-8 byte-order mark makes the first column read as \ufeffTitle and match nothing — which is why the first column is so often the one that fails.
  • Mis-detected delimiter. A semicolon-delimited export opened as comma-delimited gives you one enormous header. PrestaShop and Lightspeed E-series both produce semicolon files.

Shopify’s page notes two related parse failures from the same place: “Illegal quoting on line” and “Missing or stray quote on line”, the latter usually caused by Excel inserting curly quotes — the advice is to replace “smart” quotes with straight ones in a text editor. And if your descriptions arrive full of strange characters, the file is not UTF-8: “open the file in a text editor. Save it again, making sure that you specify UTF-8 encoding.”

How the converter prevents it

This whole error class is structural, so the defence is structural too: you never type a Shopify header. The tool writes the header row itself from its own schema — all 61 columns in the exact order of Shopify’s published template, which a golden test asserts is byte-identical to the first row of the official sample file. There is no opportunity for a typo, a stray space or a stale column name, and the output is always UTF-8.

Your side of the mapping is a dropdown, not a text field. The auto-match normalises header text before comparing — lowercasing and stripping punctuation, so Item No. matches item no — and carries a confidence badge you can overrule. The delimiter and the encoding are detected from the file’s bytes rather than its extension, which is how a semicolon-delimited PrestaShop export and a tab-separated Amazon report both load without being converted first.

What remains is the risk of mapping nothing to a column that matters. The unmapped_column rule in src/lib/validate.ts reports a warning for each of SKU, Price, Product image URL, Vendor and Inventory quantity left unmapped, quoting that column’s real constraint — because a silently missing price is exactly the failure Shopify will not tell you about. And title_missing is an error, not a warning, since a product row with no title is the one case Shopify genuinely rejects.

What a correct fix looks like

Do not hand-edit header rows to match Shopify. Map your columns once in step 3, check the confidence badges, then read the validation table — the warnings list is the answer to “what did I forget?”, which is not a question Shopify’s import report answers.

If you are updating existing products rather than creating them, keep URL handle and Title and do not drop the option columns, for the reason the reference gives: an omitted Option1 name deletes the variants you were trying to update. And before you remove any column, check whether another depends on it — Shopify’s reference warns that importing a file “with values in only some related columns results in an import error”.

The column-by-column format reference lists all 61 columns with their type, scope and constraint, if you want to see what the generated header row contains and why.

Before you retry the import

  • Fix the file, not the symptom. Shopify reports the first failure it meets, so a second error usually appears once the first is cleared.
  • Import into a development store or a draft-status batch first, so a half-correct file cannot put wrong data in front of customers.
  • If you are overwriting existing products by handle, export your live products first: a blank cell in the import can erase a value that is currently there.

Column-by-column reference: the Shopify product CSV format. Nexum Gate is not affiliated with Shopify Inc.