You push a fresh feed to Google Merchant Center. Half your catalog comes back disapproved with this in Diagnostics:
Issue: Invalid product price [price]
Attribute: price [price]
The verbatim fix Google publishes on the How to fix: Invalid product price help article is short and unhelpful:
Increase product price to a number higher than 0 unless this is a mobile device sold as part of a contract.
That's accurate for the most obvious case — products priced at zero — but the actual error fires in five different scenarios, only one of which is "the price is literally zero." This post covers all five, ranked by how often each one is the real culprit, and how to verify the fix before resubmitting.
Quick note on naming: Google surfaces this issue under several display labels depending on the Diagnostics view ("Invalid product price," "Invalid price," "Incorrect price"). The Content API issue identifier is most commonly invalid_price. The underlying validation is the same regardless of the label.
TL;DR
invalid_pricefires when Google's parser can't read thepriceattribute as a positive number with a valid currency code matching the feed's target country.- The most common cause is a CSV export that wrote the price as
"$19.99"with the dollar sign in the value, so Google parses it as a non-numeric string. - Second: missing or wrong
priceCurrency. A feed targeting Germany must useEUR, notUSD, even if the price column reads "19.99." - Third: a price of zero or negative on non-mobile-contract products. Only mobile phones and tablets sold on a carrier contract can legitimately have price = 0.
- Fourth: decimal separator wrong for the target country (comma vs period in European feeds).
- Fifth:
sale_priceset higher thanprice, which Google rejects under the sameinvalid_priceumbrella.
What invalid_price actually means
Google's product data specification defines price as a required attribute on every product. The expected format is a number plus a currency code, either as separate fields (XML feed: <g:price>19.99 USD</g:price>) or as a single string with the currency suffix (CSV: 19.99 USD).
Google's parser does several checks:
- Numeric check. The price string, after stripping the currency code, must parse as a positive real number greater than zero.
- Currency code check. The ISO 4217 code (USD, EUR, GBP, etc.) must match the currency expected by the feed's target country.
- Range check. The price must fall within a reasonable range for the product category. Extreme outliers (a t-shirt listed at $99,999) get caught here.
- Sale price relationship check. If
sale_priceis set, it must be less thanpriceand within the discount window (typically up to 90% off). - Landing page consistency check. Google crawls the landing page and compares the displayed price to the feed price. Mismatches over a tolerance threshold surface as a separate issue (
mismatched_product_price), but in some configurations they cascade intoinvalid_price.
If any of these fails, the product is disapproved and the issue logs as invalid_price.
Why Google flags it
Price is the most consumer-facing attribute on a Shopping listing. A wrong price doesn't just hurt your ad performance — it creates trust and regulatory liability for Google's marketplace. In several jurisdictions (the EU, the UK, and increasingly the US), the price advertised in a search result has to match the price the consumer pays at checkout, full stop.
Google's price validation is designed to fail loudly rather than quietly:
- Zero or negative prices indicate a placeholder, a price set incorrectly on an out-of-stock item, or a service/gift-card product that shouldn't be in Shopping at all.
- Wrong currency means the consumer sees the wrong number — a German buyer seeing "19.99 USD" is misleading even though the digits match a euro value.
- Sale price higher than regular price is a definitionally invalid sale and a common indicator of an integration bug.
- Non-numeric price strings ("Call for price," "Contact us," "TBD") aren't allowed under any circumstances.
When any of these fails, the product is disapproved entirely until the feed is corrected.
Five fixes ranked by frequency
Fix 1: Strip currency symbols and non-numeric characters from the price value
The single most common cause of invalid_price. A feed export contains prices like:
$19.99
£24.99
€29,99
19.99 USD$
The dollar sign, pound sign, euro sign, and trailing currency suffix all get included as text in the price value. Google's parser tries to read "$19.99" as a number, fails, and disapproves.
The correct format is the numeric value alone, with the currency code in a separate field or as a suffix exactly once:
price: 19.99 USD
Where this goes wrong:
- Shopify CSV exports through the Shopify admin Export. The default export writes prices as plain numbers, but some custom export apps prefix the currency symbol.
- WooCommerce CSV exports from the WooCommerce Product Importer often include the currency symbol when locale formatting is enabled.
- BigCommerce custom exports depend on the column template; defaults are usually clean, custom ones often aren't.
- Spreadsheet copy-paste from accounting software. QuickBooks, Xero, and similar tools format prices for human reading and that formatting carries into copy-paste operations.
The fix: regenerate the feed with prices as plain numbers. If you're working with a CSV in Excel or Sheets, format the price column as Number (not Currency) before exporting.
For the Content API and Merchant API: prices are submitted as a structured object with amountMicros and currencyCode fields. The numeric value is in micros (multiply by 1,000,000), and the currency is a separate three-letter code. Symbol bugs effectively don't happen in API submissions — they only happen in CSV and XML feeds.
Fix 2: Match the currency to the feed's target country
Every Merchant Center feed has a target country, set when you create the feed. The currency you submit must match the official currency of that country, or use a multi-currency configuration if your account is set up for it.
The most common mismatch patterns:
- Shopify store set to US default but selling internationally; feed prices come through as USD even though the target country in Merchant Center is the UK.
- A merchant duplicating a feed for a new target country and forgetting to swap the currency.
- BigCommerce stores with multi-currency enabled where the export pulls the "base" currency instead of the target.
The fix is to pick one of two approaches:
Single-currency target: make sure every product's price currency matches the feed's target country (USD for US, EUR for EU country feeds, GBP for UK, JPY for Japan, CAD for Canada, etc.).
Multi-currency: if you're submitting one feed to multiple countries with different currencies, use a multi-country feed configuration in Merchant Center and submit per-country price overrides via the [country]_price or pricing structures rather than relying on a single price value.
The full list of accepted currency codes is the ISO 4217 standard, available in Google's currency code reference.
Fix 3: Filter out zero-priced and negative-priced products
If a product's price is 0 or below, Google disapproves it. The only documented exception is mobile phones and tablets sold under a carrier contract where there is no upfront cost (and even that exception doesn't apply in Latin American countries, where the full unsubsidized cost has to be listed).
Common sources of zero-priced products:
- Gift cards priced as "from $25" without a default value
- Service products (consultations, subscriptions to non-physical content)
- Donation products
- Bundle parent products where the price is computed from children at checkout
- Out-of-stock items where someone zeroed the price as a hack to hide them
- Imported products with missing data from a supplier feed that didn't have prices populated
The fix depends on the case:
For gift cards, services, donations, and bundle parents: exclude them from the feed entirely. They shouldn't be in Shopping. Use Shopify's "Sales channels" toggle, WooCommerce's product visibility, or a feed-rule filter to exclude them.
For out-of-stock hacks: set availability to out_of_stock and let Google handle the visibility properly. Zero-pricing the item is the wrong lever.
For supplier-feed gaps: hold the feed until prices are populated. Submitting incomplete data trains Google's account-level scoring against you.
Fix 4: Use the correct decimal separator for the target country
European feeds frequently break on this. The convention varies:
- US, UK, Japan, Canada (en-CA): period as decimal separator, comma as thousands separator →
1,234.56 - Most EU countries (Germany, France, Italy, Spain, etc.): comma as decimal, period as thousands →
1.234,56 - Some others vary by locale
Google's parser is generally tolerant of either separator for the decimal but trips when the value is ambiguous. 19,99 is unambiguous (no period present) and reads as 19.99 in EU locales. 1,234 is ambiguous — is it one thousand two hundred thirty-four, or one point two three four? Google generally treats it as 1,234.00 in US feeds and 1.234 in EU feeds, but the parsing can fail silently.
The safest format across all target countries: use the period as the decimal separator and omit thousands separators entirely.
1234.56 # safe everywhere
1,234.56 # US-style, fails some EU parsers
1.234,56 # EU-style, fails US parsers
For prices under 1,000 the issue rarely shows up; for high-ticket items (furniture, electronics, jewelry), it surfaces fast.
Fix 5: Verify sale_price is less than price, not greater
Google rejects sales where sale_price >= price. Common causes of inversion:
- Compare-at-price misuse on Shopify. Some merchants put the sale price in
priceand the original price incompare_at_price, and a feed plugin that mapscompare_at_price→sale_priceproduces an inversion. - Currency rounding mismatches. A USD
priceof 19.99 converted to GBP at a slightly different exchange rate than thesale_pricecan produce sale_price > price by pennies. - Stale sale data. A sale ended in the source system,
pricerose back to the original value, butsale_priceis still set to the (now-higher) old "sale" value.
The fix: validate the inequality sale_price < price in your feed-generation step before submission, and either skip the sale_price field for products that fail the check or correct the values upstream.
sale_price_effective_date adds another layer of validation — sales submitted outside the effective date window can also trigger invalid_price. If you use date-windowed sales, make sure your feed regenerates frequently enough that out-of-window sales are removed before they reach Google.
How to verify the fix
After updating the feed, validate before the next review cycle.
1. Check a sample of fixed products in Merchant Center. Go to Products > All products, filter by the affected feed, and click into a few products. The "Price" line should show a clean numeric value and the right currency. If it shows the raw string from your CSV with symbols, your feed is still submitting bad data.
2. Coverage check from the command line. A simple sanity check:
# How many products have a numeric-parseable price?
xsv select price feed.csv | tail -n +2 | \
awk '{ gsub(/[^0-9.,-]/,"",$0); if ($0+0 > 0) ok++; else bad++ } END {print "OK:", ok, "Bad:", bad}'
If the "Bad" count is non-zero, you have rows where the price isn't a clean positive number. Inspect them and fix at source.
3. Currency consistency check:
# Show distinct currencies in the feed
xsv select price feed.csv | tail -n +2 | awk '{print $NF}' | sort -u
For a single-target feed, the output should be exactly one currency code. Multiple codes mean the feed is mixing currencies, which will trip the country-match check.
4. Wait for the recrawl. Re-review typically completes within 24 to 72 hours of the next feed fetch. Don't resubmit hourly; each submission resets a soft review clock on every product in the feed.
What not to do
- Don't paper over the issue by hardcoding a placeholder price. Setting every zero-priced product to "1.00" gets them into Shopping but generates lots of
mismatched_product_priceerrors against the landing page, which is a worse problem. - Don't push the same feed unchanged hoping Google re-reviews. It re-fetches automatically on its own schedule. Unchanged resubmissions delay re-review on other products in the feed.
- Don't submit
0.01to dodge the zero-price rule on gift cards. Google's category-range check catches it and flagsinvalid_pricefor being out-of-range for the product category. - Don't rely on "Sale" badges to compensate for an inverted
sale_price. Google's parser checks the inequality before any display logic; a bad inequality means disapproval regardless of how the badge would render.
How SnowPipe handles this
SnowPipe syncs Shopify, WooCommerce, and BigCommerce catalogs to Google Merchant Center via the Merchant API v1. Three design choices in SnowPipe directly head off invalid_price:
Structured price submission. Because SnowPipe submits to the Merchant API rather than emitting CSV or XML feeds, prices go to Google as amountMicros integers paired with an ISO 4217 currency code. Currency-symbol injection bugs (Fix 1 above) effectively can't happen in the SnowPipe path.
Per-connection currency enforcement. When a GMC connection is configured for a target country, SnowPipe validates that every outgoing price's currency matches the country's expected currency. Products with mismatched or missing currency are flagged in the Products tab before submission instead of being silently disapproved by Google.
Sale price inequality validation. Before any product is submitted, SnowPipe checks that sale_price < price and that sale_price_effective_date includes the current time. Inverted or out-of-window sales are surfaced as warnings in the Products tab with a one-click toggle to either fix the inequality or drop the sale price for that product.
You can see price-validation results and per-product currency breakdowns in the Products tab of every GMC connection, with deep links to the source store admin for fixes.
Summary
invalid_price is usually a parsing or formatting issue, not a "set the price to a number" issue. The five real causes — symbols in the value, wrong currency for the target country, zero-priced products that shouldn't be in Shopping, ambiguous decimal separators, and inverted sale prices — each have a clean fix at the source. Submitting clean structured prices (Merchant API) avoids the whole category of formatting bugs. For CSV and XML feeds, validate the inequality sale_price < price and the currency-country match before every submission. Re-review takes 24 to 72 hours after the next successful fetch.
Tired of fighting GMC price errors one feed at a time?
Try SnowPipe free — connect your store and get pre-flight price validation plus accurate Google/Facebook syncs in minutes. Or, book a 15-min demo and I'll walk you through your specific setup.