The selected_or_first_available_variant can return an unavailable variant

Imagine you have a product like randomly selected Nike shoe that comes in both “Regular” and “Wide”, and you want to hide the unavailable Colors for the “Wide” fit and include 15-18 shoe sizes for the “Wide” fit:

Pretty standard stuff. As a merchant, you don’t make every combination of every sizing option because large feet tend to be wide feet. You don’t make mens size 18 shoes in “pink and blue” because there isn’t enough demand. And you organize your option groups by “upper things constrain lower things”.

As a developer you already know:

  • Product pages have a selected_variant if the product page has a valid variant param.
  • Products in a collection have selected_variant if filters apply to a specific variant
  • The product form does not always have a selected_variant but each option group always has a selected option. There’s no “select a size” group on the server.
  • In a section-rendering-api call each option_group always has a selected value, and that value is determined by the selected_or_first_available_variant logic.

Here’s what you might expect:

  • Passing in an incomplete set of option_values to represent “Fit” or “Color” would combine with selected_or_first_available_variant such that the unspecified option values would select an available variant if one exists.

That is not how it works.

:right_arrow: As far as I can tell, the selected_or_first_available_variant logic runs first and option_value params are applied after.

There is no server logic ensuring that the form state will lead to an available variant when partial option_value params are passed in and there is no way to distinguish option values that only have sold out variants below from options that have no variants below.

What this means:

Product form
If you want to hide “unavailable” variant combinations in a top-down product form (think make/model/year for cars) you cannot treat the product URL with params as the source of truth. You have two choices:

  • A. Untether the state of the product form in the client from the state in the URL/server
  • B. Use iterative section-rendering-api calls to search the space of option_values combinations until you find a combination that leads to a variant or a path that is available

Collection pages
Product cards with “color swatches” cannot accurately represent price, availability, or sold out states if the “color” option group is not the first option_group on the product form.

Proposal

  1. Introduce .exists for option groups to distinguish “sold out” from “valid combination”

product_option_value.available — stays the same

product_option_value.exists — tells you whether that option can lead to a variant

  1. Introduce a new param for ?path=[avaialable,exists]

If the param is not present we keep the current behavior where selected_or_first_available_variant does not consider the currently selected option_values.
This ensures no breaking changes.

Passing in the path tells the server what state to represent for selected_or_first_available_variant

Hey @Gideon, appreciate you flagging this as well.

selected_or_first_available_variant can return a selected variant regardless of availability, and partial option_values selections aren’t guaranteed to be completed into a purchasable combination. However, you’re right that product_option_value.available only represents purchaseability, it doesn’t distinguish between a subtree where every variant is sold out and one where no variants exist.

That makes the proposed exists state a valid capability gap, particularly for sparse variant trees and collection swatches on non-leading options. I’m happy to pass that feedback along on our end for sure.

Could you share a minimal option/variant matrix and one example Section Rendering request showing the unexpected values for selected, available, variant, and selected_or_first_available_variant? That’ll help confirm whether there’s a separate bug in addition to the missing exists state.

For now, available should work when sold-out and nonexistent combinations can be treated the same. Where that distinction matters, maintaining the variant state client-side or iteratively requesting complete combinations appears to be the available workaround, not super ideal though, as you mentioned.

Let me know if I can help clarify anything on our end here and hope to hear back from you soon.