Storefront GraphQL API responses include unpublished variants

Hi there,

We’re happy that the product variants are finally Publishable, however we started observing some inconsistent behaviour with it recently.

Our expectation is, just like Product type, if a ProductVariant is unpublished from the specific headless sales channel that’s making the request to Storefront GraphQL API, that unpublished ProductVariant should be no part of the API responses, in any context.

What we’re currently experiencing is, even though their options are not available as a ProductOption inside Product object, the unpublished variants are still a part of the variants connection. We believe this is not the intended behaviour, since the other Publishables (Products and Collections) are never returned when they’re unpublished from the headless sales channel.

Example response from Storefront GraphQL API (2026-07) when querying a collection with its products and their variants:

{
  "data":{
    "collection":{
      "id":"gid://shopify/Collection/631488446793",
      "products":{
        "nodes":[
          {
            "id":"gid://shopify/Product/8849963581769",
            "variants":{
              "nodes":[
                {
                  "id":"gid://shopify/ProductVariant/49340924592457",
                  "sku":"Z030-003-001",
                  "selectedOptions":[
                    {
                      "name":"Size",
                      "value":"FLATE® Barista Rack"
                    }
                  ]
                },
                {
                  "id":"gid://shopify/ProductVariant/49340924625225",
                  "sku":"Z030-003-002",
                  "selectedOptions":[
                    {
                      "name":"Size",
                      "value":"FLATE® Towel Rack, Neue SKU: Z030-003-003"
                    }
                  ]
                }
              ]
            },
            "options":[
              {
                "id":"gid://shopify/ProductOption/11451579269449",
                "name":"Size",
                "optionValues":[
                  {
                    "id":"gid://shopify/ProductOptionValue/933798936905",
                    "name":"FLATE® Barista Rack"
                  }
                ]
              }
            ]
          },
          {
            "id":"gid://shopify/Product/15081512665468",
            "variants":{
              "nodes":[
                {
                  "id":"gid://shopify/ProductVariant/54994894619004",
                  "sku":"Z030-003-003",
                  "selectedOptions":[
                    {
                      "name":"Size",
                      "value":"FLATE® Towel Rack"
                    }
                  ]
                }
              ]
            },
            "options":[
              {
                "id":"gid://shopify/ProductOption/17434101940604",
                "name":"Size",
                "optionValues":[
                  {
                    "id":"gid://shopify/ProductOptionValue/9205131608444",
                    "name":"FLATE® Towel Rack"
                  }
                ]
              }
            ]
          }
        ]
      }
    }
  }
}

X-Request-ID: a35096d6-feb5-467a-ae00-173c5d459dd5-1780565675

In this instance, ProductVariant with ID gid://shopify/ProductVariant/49340924625225is unpublished from the headless sales channel making this request.

We’ve also noticed that instead of using an API key belongs to a Headless Sales Channel, using a Storefront API key belongs to a legacy custom app actually returns a correct response, not including unpublished product variants at all. (Permissions for both apps are the same.) This duality kind of confirms that it’s a bug rather than an intended feature for us.

X-Request-ID with the legacy custom app’s Storefront API key: 5fe74bc7-0aa0-45eb-88fa-94be5e188114-1780566252

Can you please check this behaviour and let us know?

cc @Alan_G since this looks similar to this topic you’re currently having a look.

Thanks!

Hey @guney.cobanoglu - thanks for the detailed write-up and for including both request IDs.

I checked the requests on our end, and it looks like both are hitting the same 2026-07 Storefront GraphQL path with the same query, but the Headless channel token and legacy custom app token are resolving through different channel contexts. Based on the current variant publishing behaviour, an unpublished variant shouldn’t be returned for the channel making the Storefront API request, so the difference you’re seeing does look worth looking into.

I’m going to raise this internally with the request IDs and variant details you shared. In the meantime, the safest workaround would be to keep using the token/context that returns the correctly filtered response, or filter those known unpublished variants server-side if you’re already reading publication state through the Admin API.

I’ll loop back here once I have an update.