Add to Cart stays enabled on an out-of-stock variant after viewing an in-stock one
Affects: Cornerstone 6.21.0 and current master · assets/js/theme/common/product-details-base.js
What happens
Pick a variant that is in stock, then switch to one that is out of stock. Add to Cart stays enabled, the sold-out alert stays hidden, and the wallet buttons stay visible — the shopper can add the out-of-stock variant to the cart. Going straight to the out-of-stock variant does not reproduce it, but most storefronts preselect an in-stock option on load.
Verified by running 6.21.0 with stencil start against a live store.
Cause
BigCommerce reports every stock key as null for an out-of-stock variant:
updateBackorderContext() only writes when the value is a number, so 1240 survives the switch:
if (typeof data.available_to_sell === 'number') {
this.context.availableToSell = data.available_to_sell;
}
updateDefaultAttributesForOOS() then falls back to that stale number and treats it as the new selection's:
const dataAvailableToSell = typeof data.available_to_sell === 'number'
? data.available_to_sell
: parseInt(this.context.availableToSell, 10) || 0;
const canSell = data.instock || dataAvailableToSell > 0;
Visible proof: after the switch, a large quantity on the out-of-stock variant reports The maximum purchasable quantity is 1240 — the previous variant's stock. updateWalletButtonsView() repeats the same expression.
Fix
Clear the figure when the key is present but not a number, rather than keeping the previous one:
if ('available_to_sell' in data) {
this.context.availableToSell = typeof data.available_to_sell === 'number'
? data.available_to_sell
: undefined;
}
Same for available_on_hand / stock and available_for_backorder. The verdict then falls to instock / purchasable, which the platform answers for every selection — a backorderable selection with zero on hand still comes back instock: true, so nothing sellable loses its button. Treating null as 0 also stops the symptom but conflates "no figure" with "none left"; restoring the page-level figure reintroduces the bug whenever that figure is positive.
Worth doing at the same time: read unlimited_backorder off the response instead of the context, so a flag left by the previous selection cannot decide the current one.
Second, smaller defect
templates/components/products/product-view.html hides the sold-out alert only while available_to_sell is above zero. A product with an infinite backorder limit reports available_to_sell: 0 (its on-hand count), so the page renders "Sold Out" above a live Add to Cart button. A product with options gets corrected by the next option-change response; one without options never does.
{{#unless product.out_of_stock}} style="display:none"
{{else}}{{#or product.available_to_sell product.unlimited_backorder}} style="display:none"{{/or}}{{/unless}}
Add to Cart stays enabled on an out-of-stock variant after viewing an in-stock one
Affects: Cornerstone 6.21.0 and current
master·assets/js/theme/common/product-details-base.jsWhat happens
Pick a variant that is in stock, then switch to one that is out of stock. Add to Cart stays enabled, the sold-out alert stays hidden, and the wallet buttons stay visible — the shopper can add the out-of-stock variant to the cart. Going straight to the out-of-stock variant does not reproduce it, but most storefronts preselect an in-stock option on load.
Verified by running 6.21.0 with
stencil startagainst a live store.Cause
BigCommerce reports every stock key as
nullfor an out-of-stock variant:updateBackorderContext()only writes when the value is a number, so1240survives the switch:updateDefaultAttributesForOOS()then falls back to that stale number and treats it as the new selection's:Visible proof: after the switch, a large quantity on the out-of-stock variant reports
The maximum purchasable quantity is 1240— the previous variant's stock.updateWalletButtonsView()repeats the same expression.Fix
Clear the figure when the key is present but not a number, rather than keeping the previous one:
Same for
available_on_hand/stockandavailable_for_backorder. The verdict then falls toinstock/purchasable, which the platform answers for every selection — a backorderable selection with zero on hand still comes backinstock: true, so nothing sellable loses its button. Treatingnullas0also stops the symptom but conflates "no figure" with "none left"; restoring the page-level figure reintroduces the bug whenever that figure is positive.Worth doing at the same time: read
unlimited_backorderoff the response instead of the context, so a flag left by the previous selection cannot decide the current one.Second, smaller defect
templates/components/products/product-view.htmlhides the sold-out alert only whileavailable_to_sellis above zero. A product with an infinite backorder limit reportsavailable_to_sell: 0(its on-hand count), so the page renders "Sold Out" above a live Add to Cart button. A product with options gets corrected by the next option-change response; one without options never does.