Dedicated to the Hydrogen framework, headless commerce, and building custom storefronts using the Storefront API.
Hi there,
I'm working on a project that uses the shopify-buy library in a webapp to interact with the Storefront API and allow users to shop on our site and complete the order on shopify.
When the user chooses to add an item to their cart we create a checkout and store the checkout id locally in the browser's localstorage. We periodically verify that the checkoutid is valid using client.checkout.fetch(checkoutId).
We've noticed that for checkout ids that no longer exist, the fetch method returns null. that is the graphql response is:
{ "data": { "node": null } }
however, if we perform a mutation (for example using client.checkout.addLineItems) with this expired/removed checkout id, the API returns an explicit error:
{"data":{"checkoutLineItemsAdd":{"userErrors":[{"field":["checkoutId"],"message":"Checkout does not exist"}],"checkoutUserErrors":[{"field":["checkoutId"],"message":"Checkout does not exist","code":"INVALID"}],"checkout":null}}}
Additionally, if I hack at the b64 checkout id to make it invalid, client.checkout.fetch does raise an error that we can handle with .catch():
{ message: 'Variable $id of type ID! was provided invalid value', ... some more details }
Is the `null` response from the Checkout query intentional, or should we expect to see a graphql error here which is propagated to the SDK error handler?
Thanks
I've been looking through the shopify documentation tutorials and documentation a bit more and it looks like this might be the expected behaviour. From https://www.shopify.com/partners/blog/shopify-graphql-learning-kit I see
You can easily get a product’s GraphQL ID for this query from the response to our previous "Connections and Edges" query. If you don't do this, you'll get a "null" response, since you're looking for a product ID that doesn't exist within your shop.
I've had a look through some more of the GraphQL documentation and can't find anything that explicitly says that these queries return null if there is no match. Specifically I looked at https://shopify.dev/concepts/graphql/benefits and the pages linked from it, https://shopify.dev/docs/storefront-api/reference/queryroot?api[version]=2020-07, and https://shopify.dev/docs/storefront-api/reference/object/checkout?api[version]=2020-07. None of these pages explicitly say that an unknown ID will return null.
Is this a standard GraphQL pattern, to return null if an item doesn't exist? In other GraphQL APIs that I've used, some queries can return an empty list if there are no matching items. I guess that doesn't make sense in the case of this API, which returns a single item. Can you recommend a place where this behaviour is documented? Either in the shopify API docs, some graphql specification, or the shopify-buy sdk documentation?
Thanks!
I've experienced this issue as well on my headless storefront, and we're using Storefront API 2021-07. I find it strange that if you pass a dummy checkout id like "abc123", the Storefront API returns an error message saying that the checkout id is invalid. Using a checkout id from my development store, I was able to reproduce this behavior hinting that the checkout id can not be found, but this doesn't explain why a checkout id related to the correct store would create this behavior, especially if that checkout id is not expired. Developers need to know why the checkout is expired so they can notify their customers rather than just emptying their cart.
A workaround for this unintended behavior is to always check that the cached checkout id returns a checkout. If it returns null, remove the localStorage item and create a new checkout. This issue rarely happens, and the solution isn't ideal, it's better than losing revenue because of a broken cart.