productVariants query shows incorrect results for automated collections that use metafields

productVariants query shows incorrect results for automated collections that use metafields

Here’s an example of a collection:

Notice that this collection has no products in it.

Now try to query the product variants in this collection:
{
productVariants(first: 250, query: “collection:320828702878”) {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
id
displayName
}
}
}
}

This will return 250 product variants in my case which is not correct.

Note that the products query below works as expected:
{
products(first: 250, query: “collection_id:320828702878”) {
pageInfo {
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
id
}
}
}
}

(also note that the inconsistency between collection and collection_id is warranted, you can check productVariants - GraphQL Admin vs products - GraphQL Admin)

The productVariants endpoint working incorrectly is not something new, this endpoint has had issues for several years. In the past the endpoint sometimes would result in an error on the Shopify webserver, other times the endpoint would show no results when that was incorrect, and more recently the API would actually show an error message that the endpoint does not support metafield collections. But this new failure mode is a new one I believe.

1 Like

Hey @Chris_Geelhoed

To help troubleshoot this, can you add the search query syntax debugging headers to your request. Adding "X-Shopify-Api-Search-Syntax-Debug": "true" to your request headers will show exactly how we’re interpreting your collection filter. The debug information should reveal if there’s a parsing issue specifically related to metafield conditions in the collection definition.

Hi Kyle, thank you for looking into this for me.

I am running this curl request and I am not seeing any additional information. What should I expect to see?

curl -v -X POST
https://price-scheduler-production-test.myshopify.com/admin/api/2025-04/graphql.json
-H ‘Content-Type: application/json’
-H ‘X-Shopify-Access-Token: <ACCESS_TOKEN>’
-H ‘X-Shopify-Api-Search-Syntax-Debug: true’
-d ‘{
“query”: “query { productVariants(first: 1, query: "collection:320828702878") { edges { node { id product { id } } } } }”
}’

Hey @Chris_Geelhoed ,

Sorry about that, the headers should be Shopify-Search-Query-Debug=1

When you add that, you’ll get a response with the search fields included:

"search": [
            {
                "path": [
                    "productVariants"
                ],
                "query": "collection:320828702878",
                "parsed": {
                    "field": "collection",
                    "match_all": "320828702878"
                }
            }
        ]

When I’m testing here, another reason for the unexpected results could be that the metafield you’re using isn’t admin filterable. That will need to be set to true

Thanks Kyle, yes that works:

{“data”:{“productVariants”:{“edges”:[{“node”:{“id”:“gid://shopify/ProductVariant/35581878403230”,“product”:{“id”:“gid://shopify/Product/5553494589598”}}}]}},“extensions”:{“cost”:{“requestedQueryCost”:4,“actualQueryCost”:4,“throttleStatus”:{“maximumAvailable”:2000.0,“currentlyAvailable”:1996,“restoreRate”:100.0}},“search”:[{“path”:[“productVariants”],“query”:“collection:320828702878”,“parsed”:{“field”:“collection”,“match_all”:“320828702878”}}]}}

One thing to note is that the metafield being used on the smart collection is a product variant metafield. Could that be important?

Hey Chris,

Yes that is important. Currently Variant metafields aren’t available for filtering, so the metafield will have to be a product metafield. https://help.shopify.com/en/manual/custom-data/metafields/filtering-products

One thing to keep in mind is that collections will still add all variants from the product even when only one of the variants has the metafield, so adding the metafield at the product level should still give the same functionality (as it relates to smart collections).

If that’s not possible, another workaround would be to query the collection directly. Example query of that below.

{
    collection(id: "gid://shopify/Collection/672173555734") {
        products(first: 10) {
            nodes {
                variants(first: 10) {
                    nodes {
                        id
                    }
                }
            }
        }
    }
}

Thanks for that information Kyle, I appreciate it. The way that our app works is that a merchant uses the resource picker to select a collection, and then we use collection ID in the graphQL query I shared above.

Specifying first: 10 on both the product and the variant is not reliable because of course there could be more than 10 products in the collection as well as more than 10 variants for a product. Managing two different cursors and paginating in a way allowed within the GraphQL API cost is very inefficient.

We also need to be able to do queries like this:

query: “collection:320828702878 OR collection:SOME_OTHER_COLLECTION”

You many consider this a feature request, but I think it is reasonable to expect that the productVariants query can be used with automated collections based on variant metafields.

In any case, even if Shopify is ok with certain automated collections not working with the productVariants query, the endpoint should definitely not return all products because this is certainly not expected. If it can’t return the correct variants then it would be better to return no variants in my opinion.

Hey Chris,

I was just using first 10 as an example, but you have a good point on having to paginate through two different cursors when you’re only looking for the product Variants. I’ll pass this feedback on for you.

As for the full response instead of getting an empty response, this happens when querying for a field that doesn’t exist (the filterable field in this case), resulting in the query being ignored. At the least an error message would help. I’ll pass that feedback on as well.

Thanks Kyle. Yes having two cursors under the current API cost system doesn’t really work, and it will work even more poorly when the variant limit is increased.

The collection field definitely does exist. It’s just that for whatever reason, certain collections (automated collections based on product variant metafields in this case) are not supported. I do agree that having an error makes a lot more sense than the current behaviour.

Just to make the issue more clear, here is a real world example:

  • App has a UI where the merchant picks a collection and the app discounts the price of all variants in that collection by 10%
  • Merchant selects an automated collection based on a variant metafield
  • Because of this special limitation (or bug depending on who you ask) now all the products in the store get discounted
  • Merchant loses money and gets mad :upside_down_face:
  • Issue above could be avoided if API worked as expected

At the end of the day all we are asking for is a reliable way to get the product variants that belong to a collection.

Thanks again for looking into this, I’m sure that you guys have some challenging technical constraints and database queries running behind the scenes.

Hey @Chris_Geelhoed

Update for you, we have looked closer at this and it would be expected for the query to return empty as opposed to returning all of the results. We are working on a fix for this. I don’t have a specific timeline, but I am keeping an eye on it and will let you know once it’s in place.

Thanks Kyle

I would say that for the query that I shared, the expected result is that the product variants belonging to the automated collection are returned.

Returning no items is still a bug, just a bug that isn’t as bad as returning all product variants like the endpoint does currently.

In any case, thank you for looking into this for me and thank you for helping with this.

1 Like

Thanks for that @Chris_Geelhoed .

I wanted to let you know that the “fix” is in place and should now be returned empty instead of the full list of variants.

The last piece of the puzzle, the feature request to make productVariant metafields filterable (in the same way products are) is still with our team and would be part of an API release when added. The developers changelog is where that would be announced.

Thanks again for sticking with this and the amazing context you’ve provided to ensure the issue was properly understood!

Thank you for the help Kyle, I appreciate it

1 Like