DEV Community

One Shopify variant reported 999,999 units in stock — and it wasn't a bug

FetchSmith on September 19, 2026

Every Shopify storefront publishes its full product catalog as public JSON. No login, no API key, no headless browser: GET https://<store-dom...
Collapse
 
dododata profile image
Dodo Data •

Confirmed the 999,999 sentinel on allbirds here too (Free Returns Coverage, inventory_management: null).

One more trap on the same payload: the discount roll-up. Min price vs min compare-at still crosses variants. A $10 accessory sitting next to a $100 jacket marked down from $120 produces a discount that belongs to neither of them. Per variant, then take the best, is the only version that survives a spot check:

const discounts = variants
    .filter((v) => v.compare_at_price && +v.compare_at_price > +v.price)
    .map((v) => Math.round((1 - +v.price / +v.compare_at_price) * 100));
const bestDiscount = discounts.length ? Math.max(...discounts) : null;
Enter fullscreen mode Exit fullscreen mode

Same class of bug as the sentinel: it produces a plausible number rather than an obvious error, so nothing downstream catches it.

Also, on the per-product endpoint the variants carry price_currency and compare_at_price_currency — so if you are already paying for the detail request you can skip meta.json for currency. The bulk feed still needs it.

Collapse
 
launchgatecheck profile image
Launch Gate •

The three-outcome model at the end is especially important. I would carry the same distinction into the stored record: source_status (ok, disabled, fetch_failed), product_count, and filtered_count as separate fields instead of encoding all of them as an empty array. That keeps a later successful retry from looking like inventory suddenly appeared.

For the 999999 sentinel, I would preserve the raw number only alongside an explicit inventory_tracked: false. Otherwise someone exporting the normalized rows to CSV can lose the predicate and accidentally reintroduce the bad aggregate downstream.

Collapse
 
nikhil_patel_10 profile image
Nikhil Patel •

The 999999 sentinel is a really interesting edge case. It’s a good reminder that Shopify product data shouldn’t always be treated as straightforward numeric values, especially when building inventory or catalog aggregation logic. Filtering on inventory management before calculating totals is a simple fix, but an easy detail to miss.