Skip to main content

Shopify CSV 'Illegal Quoting' and Duplicate Variant Option Errors: Fixes That Work

9 min readPipeSheets Team

If your Shopify product upload dies with 'illegal quoting in line 2' or 'Options are not unique', the file itself is fine to Shopify's eye until the parser hits one bad row. 'Illegal quoting' means a double-quote in that line is unmatched or curly (a smart quote from Word or Google Docs), or a stray comma broke an unquoted field. 'Options are not unique' means two variant rows under the same Handle carry the identical Option1/Option2/Option3 value combination. Both errors are row-level, and both are fixable without rebuilding the file from scratch.

This guide covers only these two error families in depth. If you want the broad tour of every Shopify import failure, that is a separate post. Here we go deep on quoting and variant options because they account for the majority of stuck uploads, and because the official error text points you at the wrong thing more often than not.

Why does Shopify say 'illegal quoting in line X'?

Shopify's CSV parser follows RFC 4180 quoting rules. A field that contains a comma, a line break, or a double-quote must be wrapped in straight double-quotes ("), and any literal double-quote inside that field must be doubled (""). When the parser opens a quote and never finds a clean closing quote before the row ends, it reports 'illegal quoting' and stops. The line number it gives you is where the parse broke, which is often one row after the row that actually caused it.

Four things trigger this in real product files:

The usual causes of an illegal quoting error:

  • Smart or curly quotes (“ ” ‘ ’) pasted from Word, Google Docs, or a web page. Shopify treats them as literal characters, not field delimiters, so a description that opens with a curly quote never closes cleanly.
  • An unmatched straight quote: a Body (HTML) or description field with one " and no partner, common when copy is trimmed mid-sentence.
  • A stray comma inside a field that was never wrapped in quotes, so the comma is read as a new column and the row count no longer matches the header.
  • Non-UTF-8 encoding (Latin-1, Windows-1252, or a file saved from Excel as 'CSV' on some locales), where accented characters and quotes get mangled into byte sequences the parser rejects.

Before and after: fixing a broken quoted field

Here is a real pattern. The description contains a comma and an inch mark, but the field was pasted with a curly opening quote and never wrapped in straight quotes. The parser opens on the curly quote's neighbor and runs off the end of the row.

# BROKEN - curly quote + unquoted comma in Body (HTML)
Handle,Title,Body (HTML),Vendor
wall-shelf,Floating Shelf,“Rustic, 24” oak shelf,Acme

# The comma after “Rustic makes Shopify read an extra column,
# and the curly quotes are never recognized as delimiters.
# FIXED - straight quotes wrap the whole field, inner quote doubled
Handle,Title,Body (HTML),Vendor
wall-shelf,Floating Shelf,"Rustic, 24"" oak shelf",Acme

# The field is wrapped in straight double-quotes so the comma is safe,
# and the literal inch mark is written as "" (a doubled double-quote).

Two rules do the heavy lifting: convert every curly quote to a straight quote, and make sure any field holding a comma or a quote is wrapped in straight double-quotes with inner quotes doubled. Do this in a plain-text editor or a tool that respects encoding, not by re-saving in Excel, which frequently reintroduces smart quotes and can switch the delimiter to a semicolon on some regional settings.

The line number in 'illegal quoting in line X' is where parsing broke, not always where the bad character sits. Check the row above the reported line too. An unclosed quote on line 40 can surface as an error on line 41 or later, once the parser finally gives up.

The encoding half of the problem

Shopify requires the file to be saved as UTF-8 with LF-style line endings, and the file must be under 15 MB. If your export is Windows-1252 or has a byte-order mark, quotes and accented vendor names can arrive as garbled bytes that the parser reads as stray quoting. Re-saving as clean UTF-8 fixes a surprising share of 'illegal quoting' reports that look like a punctuation problem but are really an encoding problem. This is one place PipeSheets helps directly: it reads files in whatever encoding they arrive in, standardizes to UTF-8, and exports a CSV without silently mangling the quotes the way a spreadsheet round-trip does.

Why does Shopify say 'options are not unique'?

In a Shopify product CSV, every variant of one product is a separate row, and all of those rows share the same Handle. That Handle is how Shopify groups the rows into a single product. Within that group, each variant must have a unique combination of Option1 Value, Option2 Value, and Option3 Value. If two rows under the same Handle land on the same combination, for example two rows that both say Size = Medium and Color = Black, Shopify rejects the product with 'Options are not unique'.

The error usually comes from one of these situations:

What actually produces a duplicate-option failure:

  • Two identical variant rows: the same handle with the same Option1/Option2/Option3 values, often a copy-paste slip or a merge that doubled a row.
  • Near-duplicates masked by whitespace or case: 'Medium' versus 'medium ' with a trailing space read as two different values by your eye but collapse to a clash, or the reverse where a stray space makes rows that should merge look distinct.
  • The same Handle reused for a genuinely different product elsewhere in the file, so two unrelated products get folded into one and their options collide.
  • A single-variant product that is missing its Option1 Name and Option1 Value, so multiple rows all fall back to the same default and clash.

Before and after: fixing duplicate option rows

This t-shirt has four intended variants, but two rows are identical (Medium / Black appears twice). Note the structure Shopify expects: the first row of the product carries the Option Names, and every following row for the same Handle leaves Option1 Name blank and only fills the Option Values.

# BROKEN - Medium/Black is listed twice under the same handle
Handle,Title,Option1 Name,Option1 Value,Option2 Name,Option2 Value,Variant Price
basic-tee,Basic Tee,Size,Medium,Color,Black,19.99
basic-tee,,,Small,,Black,19.99
basic-tee,,,Medium,,Black,19.99
basic-tee,,,Large,,White,21.99

# Rows 1 and 3 both resolve to Size=Medium, Color=Black -> Options are not unique.
# FIXED - four unique option combinations, names only on the first row
Handle,Title,Option1 Name,Option1 Value,Option2 Name,Option2 Value,Variant Price
basic-tee,Basic Tee,Size,Medium,Color,Black,19.99
basic-tee,,,Small,,Black,19.99
basic-tee,,,Large,,Black,21.99
basic-tee,,,Large,,White,21.99

# Every row now has a distinct Size + Color pair, and Variant Price is filled on each.

The fix is to deduplicate the variant rows so each Option combination appears once, and to make sure trailing spaces or inconsistent capitalization are not creating hidden duplicates or hidden distinctions. Trimming whitespace and standardizing case across the Option Value columns is exactly the kind of pass that surfaces these clashes before Shopify does.

Single-variant products and the 'Default Title' rule

If a product has no real variants, Shopify still expects an option. Set Option1 Name to 'Title' and Option1 Value to 'Default Title'. Leaving those blank on a product that should be single-variant is a common way to trip either a uniqueness error or a silent variant rebuild. There is a related trap worth knowing: if you are updating a variant-related column such as SKU or a weight value and you omit the Option1 Name and Option1 Value columns, Shopify creates a new default variant and deletes the existing ones. Always carry Option1 Name and Option1 Value through variant updates.

Changing a value in the Option1/Option2/Option3 Value columns on an existing product deletes the old variant IDs and creates new ones. If those IDs are referenced by inventory, orders, or third-party apps, edit option values deliberately, not as a casual cleanup.

The other variant errors that ride along

Duplicate options rarely travel alone. A few sibling failures show up in the same files:

Adjacent variant problems to check while you are in the file:

  • Duplicate handle across products: two distinct products accidentally share a Handle, so their variant rows merge and collide. Give each product its own unique, lowercase, hyphenated handle.
  • Missing Option1 Name or Value on variant rows: Shopify needs the Option Names on the product's first row and consistent Option Values on every variant row.
  • Missing Variant Price: the price field cannot be blank on a variant row. A blank price is a frequent reason a row is silently skipped or the product fails.
  • Too many variants: Shopify allows up to 100 variants per product and up to 3 options per product. A file that fans out past 100 combinations for one handle will not import as one product.
  • Inconsistent Option Names down a product: the Option1 Name that appears on the first row defines the option for the whole product; conflicting names on later rows confuse the grouping.

Preflight checklist before you upload

Run this pass on any product CSV before you hand it to Shopify. It catches both error families and most of their cousins.

Check each of these before importing:

  • File is saved as UTF-8 with LF line endings and is under 15 MB.
  • No curly or smart quotes anywhere; every quote is a straight " character.
  • Every field containing a comma, quote, or line break is wrapped in straight double-quotes, with inner quotes doubled ("").
  • The delimiter is a comma, not a semicolon (check the header row if you exported from a European locale).
  • Each product's variant rows all share one Handle, and no unrelated product reuses that Handle.
  • Within each Handle, every Option1/Option2/Option3 value combination is unique.
  • Option Names appear on the product's first row; Option Values are filled on every variant row.
  • Single-variant products use Option1 Name = Title and Option1 Value = Default Title.
  • Every variant row has a non-blank Variant Price.
  • No product exceeds 100 variants or 3 options.
  • Leading and trailing whitespace is trimmed from Handle and Option Value columns so hidden duplicates cannot form.

Cleaning the file instead of hunting line by line

Most of this checklist is mechanical: normalize encoding, replace curly quotes with straight ones, trim whitespace, standardize the case of option values so 'Black' and 'black' stop looking like two colors. Doing it by hand in a 3,000-row export is where uploads stall for an afternoon. In PipeSheets you can run a Quick Clean pass to trim whitespace and standardize the obvious noise, then use find and replace to swap curly quotes for straight quotes and a case transform to make Option Values consistent, and preview the before and after with detected column types before you export a clean UTF-8 CSV. It will not map your columns to Shopify's schema for you, so you still confirm the header names and option structure yourself, but it removes the encoding and whitespace failures that produce most 'illegal quoting' and phantom-duplicate errors.

The pattern that works: fix the encoding and quoting first so the file parses at all, then deduplicate and normalize the Option Value columns so the variants are genuinely unique. Handle those two layers and the two errors that stop most Shopify imports stop with them.

Try the automated solution

PipeSheets can fix these issues automatically. Clean your first file free.

Clean Your CSV