“Price is not a number”: currency symbols and decimal commas

Validation failed: price can’t be blank

Shopify's price column takes digits and a dot. Everything a European spreadsheet does to a number — the symbol, the comma, the non-breaking space — makes it something else.

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 product CSV reference is specific about the money columns: a number only, with no currency symbol, no thousand separator, and a dot as the decimal mark. There is no currency column anywhere in the product CSV — the store’s own currency decides what the number means.

Shopify’s common import problems page lists Validation failed: price can’t be blank with the terse instruction “The price needs to be added to this line”, and the parallel case Inventory quantity is not a number: “You need to enter a number value.”

But the reference records something worse than an error. A blank price does not fail — it defaults. Leave the cell empty and the variant imports at 0.00, published and buyable. “1.234,50” is the same hazard in a different coat: read as an English number it is 1.23, so a €1,234.50 item can go on sale for a euro and twenty-three cents, with no error anywhere.

How to find it in your CSV

Check every money column, not just Price: Compare-at price and Cost per item have the same rules. Filter for cells containing anything that is not a digit or a single dot. In practice you are looking for:

  • Currency symbols and codes — €19.99, EUR 24.99, £215.00. eBay’s listings report and POS exports both produce these.
  • Decimal commas — 45,00. PrestaShop, Wix and most German, French and Bulgarian exports write money this way.
  • Thousand separators in either convention — 1,234.50 and 1.234,50 — and the non-breaking or thin spaces some locales use instead.
  • Text where a number should be — POA, Call for price, or a blank.
  • More than two decimal places. Shopify stores two; 19.999 is not a valid money value.

How the converter prevents it

Two layers: the converter repairs what can be repaired unambiguously, and the validator refuses the rest.

Every money cell goes through a money parser that strips currency symbols (€, £, лв and the rest), the common ISO currency codes, brackets, and all whitespace including non-breaking and thin spaces — then decides the decimal mark by position rather than by guessing a locale. When both a comma and a dot are present, the rightmost one is the decimal separator, so €1.234,50 and £1,234.50 both resolve to 1234.50. When only a comma is present it is read as a decimal mark unless the cell matches the thousand-separator pattern exactly (1,234), in which case it is removed. The result is written with two decimal places.

Whatever survives that is genuinely not a number, and the money_format rule in src/lib/validate.ts reports it as an error against each of Price, Compare-at price and Cost per item:

Price value “POA” is not a plain number. Remove currency symbols and thousand separators and use a dot as the decimal mark.

The pattern it enforces is digits with at most two decimal places, so 19.999 is rejected as well as POA. And because a blank price is the silent-zero case rather than a malformed one, price_blank handles it separately as a warning on every non-image row — Price is empty — Shopify will import it as 0.00 — which keeps a genuinely free product exportable while making sure nobody ships a catalogue of accidental zeroes without being told.

What a correct fix looks like

For formatting, let the conversion handle it: load the file, check a few rows in the preview, and the prices come out as plain numbers. Do not pre-format in Excel — reformatting a column as “Number” after the file has been parsed as text is how 1.234,50 becomes 1.23 in the first place.

For currency, decide and convert yourself. The converter normalises format and deliberately never applies an exchange rate: a euro figure silently turned into pounds is a far worse outcome than one that is obviously unconverted. If your source store and your Shopify store use different currencies, multiply the column before you import.

For “POA” and genuinely unpriced lines, set a real price or leave the product as draft — the default on most presets here. A draft product cannot be bought at the wrong price while you work out the right one.

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.