Skip to content

Fix cart drawer desync on partial inventory 422#3939

Open
trippyogi wants to merge 1 commit into
Shopify:mainfrom
trippyogi:fix/cart-drawer-partial-availability-422
Open

Fix cart drawer desync on partial inventory 422#3939
trippyogi wants to merge 1 commit into
Shopify:mainfrom
trippyogi:fix/cart-drawer-partial-availability-422

Conversation

@trippyogi

@trippyogi trippyogi commented Jul 9, 2026

Copy link
Copy Markdown

PR Summary

When a customer tries to add more of a product than is available, the cart drawer now shows what was actually added to the cart instead of staying empty, while the product page still displays the availability warning.

Why are these changes introduced?

Fixes #3921

When /cart/add returns 422 after partially adding available quantity, the server cart updates but Dawn's error branch did not refresh cart drawer UI. The drawer could open empty or stay stale even though /cart.js had items and the product form showed the availability error.

What approach did you take?

In assets/product-form.js, when response.status == 422, keep existing error handling (handleErrorMessage, pubsub cartError, CartErrorEvent) unchanged, then call a new refreshCartUIAfterAvailabilityError() method for cart drawer mode.

  1. Fast path: If the 422 /cart/add response already includes sections and item_count > 0, call existing cart-drawer.renderContents(response) (same as successful add).
  2. Fallback: Otherwise fetch /cart.js to confirm item_count > 0, then use the Section Rendering API:
    • ?section_id=cart-drawer to replace .drawer__inner (removes stale empty-cart markup)
    • ?section_id=cart-icon-bubble to refresh the header bubble
    • Open the drawer if it is not already open

Cart notification mode is unchanged. Its renderContents depends on add-response line item key, so this helper is scoped to CART-DRAWER only.

Other considerations

  • Shopify Cart AJAX 422 can represent partial success: the cart may gain available quantity even when the response is an error.
  • Bundled sections HTML is returned on cart POST endpoints (/cart/add, /cart/change, etc.), not on GET /cart.js?sections=. The initial fix attempt using that GET pattern did not work.
  • Related issue Inconsistent cart state after invalid quantity update #3906 (invalid quantity update via /cart/change) is a separate code path in assets/cart.js and is out of scope for this PR.
  • No Liquid, CSS, or theme settings changes.

Decision log

# Decision Alternatives Rationale Downsides
1 Refresh via ?section_id=cart-drawer and ?section_id=cart-icon-bubble GET /cart.js?sections=...; cart-drawer-items.onCartUpdate() only Section Rendering API returns server-rendered HTML with current cart state. onCartUpdate does not remove empty-drawer markup or refresh the bubble. GET /cart.js?sections= does not return bundled section HTML. Two extra requests on 422 when add response lacks sections
2 Gate refresh on response.status == 422 and item_count > 0 Refresh on all response.status errors Matches partial inventory partial-success scope; avoids unnecessary fetches on sold-out errors with an unchanged empty cart Requires item_count check via add response or /cart.js
3 Scope to cart drawer only Shared helper for cart notification cart-notification.renderContents requires add-response key; applying same logic there needs separate validation Cart notification mode not fixed by this PR

Visual impact on existing themes

Merchants using cart drawer mode will see the drawer populate correctly when a customer over-requests quantity and Shopify partially adds available stock. The inline availability error on the product form remains visible. No change for merchants using cart page or cart notification modes. Normal successful add-to-cart behavior is unchanged.

Testing steps/scenarios

  • Clear cart. Product with tracked inventory, qty 1 available, continue selling off. Set qty 2, click Add to cart.
  • Confirm /cart/add returns 422 with availability description.
  • Confirm product form shows error (e.g. "Only 1 item was added to your cart due to availability.").
  • Confirm /cart.js reports item_count: 1.
  • Confirm cart drawer opens and shows the product at quantity 1.
  • Confirm cart bubble shows count 1.
  • Confirm normal add (qty 1, sufficient stock) still succeeds with unchanged drawer behavior.
  • Sold-out add (qty 1, stock 0): sold-out UI unchanged, drawer stays empty if cart unchanged.
  • Tested on mobile
  • Tested on multiple browsers
  • Tested for accessibility (focus trap when drawer opens after error)

Demo links

Replace theme IDs with your development theme if sharing with reviewers.

Checklist

When /cart/add returns 422 after partially adding available quantity,
refresh the cart drawer and bubble via section_id fetches so the UI
matches server cart state while keeping the product-form error visible.

Fixes Shopify#3921
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Cart Drawer UI desync: No refresh on 422 error when max inventory is reached

1 participant