Getting 404 on image urls in bulk query

Topic summary

Issue: Image URLs returned from GraphQL bulk queries contain random hash strings (appearing as UUIDs) that cause 404 errors after approximately one hour. Removing the hash from the URL allows the images to work correctly.

Technical Details:

  • The bulk query uses originalSrc field within the images node
  • Example problematic URL includes strings like 0a54da41-c627-470d-8ffb-4a1caca41e8c before the file extension
  • Regular GraphQL product queries return URLs without these random strings
  • The hash appears to be time-limited, making URLs inaccessible after a short period

Current Status:

  • A Shopify API Support team member attempted to replicate the issue but could not reproduce it—their bulk queries returned correct URLs without the hash
  • They requested the full BulkOperationRunQuery body and Request ID to investigate further
  • The issue remains unresolved and has now affected multiple users/clients, with another developer reporting the exact same problem

Next Steps: Awaiting additional debugging information from affected users to identify root cause.

Summarized with AI on November 18. AI used: claude-sonnet-4-5-20250929.

I’m submitting a bulk query for images, and they are returned in the bulk file. It looks like we’re able to access the image for a short amount of to do some calculations, but when we use the image URL after about an hour the link returns a 404. There seems to be some weird SHA attached towards the last half of the URL. If I remove the hash the image works correctly. What is going on?

Original Link

https://cdn.shopify.com/s/files/1/0211/7635/2832/products/51016_f_fm_0a54da41-c627-470d-8ffb-4a1caca41e8c.jpg?v=1652844643

link with sha removed
https://cdn.shopify.com/s/files/1/0211/7635/2832/products/51016_f_fm.jpg?v=1652844643

images portion of bulk query

...
                images {
                  edges {
                    node {
                      id
                      originalSrc
                    }
                  }
                }
...

Images returned as jsonlines.

{"id":"gid:\/\/shopify\/ProductImage\/29158816579657","originalSrc":"https:\/\/cdn.shopify.com\/s\/files\/1\/0211\/7635\/2832\/products\/51015_f_fm_7edd7d9f-619e-48c5-bb11-6aa4aa0b2679.jpg?v=1652844643","__parentId":"gid:\/\/shopify\/Product\/6755972808777"}
{"id":"gid:\/\/shopify\/ProductImage\/29158816612425","originalSrc":"https:\/\/cdn.shopify.com\/s\/files\/1\/0211\/7635\/2832\/products\/51016_f_fm_0a54da41-c627-470d-8ffb-4a1caca41e8c.jpg?v=1652844643","__parentId":"gid:\/\/shopify\/Product\/6755972808777"}
{"id":"gid:\/\/shopify\/ProductImage\/29158816710729","originalSrc":"https:\/\/cdn.shopify.com\/s\/files\/1\/0211\/7635\/2832\/products\/51017_f_fm_fd88025d-e8fe-49f0-bfbb-f41e8b462d4e.jpg?v=1652844645","__parentId":"gid:\/\/shopify\/Product\/6755972808777"}

Doing a regular graphql query on the product returns URLs without some random string in the middle:

request:

query ($ID: ID!) {
  product(id: $ID) {
    images(first: 2) {
      edges {
        node {
          originalSrc
        }
      }
    }
  }
}

response

{
	"data": {
		"product": {
			"images": {
				"edges": [
					{
						"node": {
							"originalSrc": "https:\/\/cdn.shopify.com\/s\/files\/1\/0211\/7635\/2832\/products\/51015_f_fm.jpg?v=1652869352"
						}
					},
					{
						"node": {
							"originalSrc": "https:\/\/cdn.shopify.com\/s\/files\/1\/0211\/7635\/2832\/products\/51016_f_fm.jpg?v=1652869352"
						}
					}
				]
			}
		}
	},
	"extensions": {
		"cost": {
			"requestedQueryCost": 5,
			"actualQueryCost": 5,
			"throttleStatus": {
				"maximumAvailable": 2000.0,
				"currentlyAvailable": 1995,
				"restoreRate": 100.0
			}
		}
	}
}

Hey @kchan - thanks for getting in touch, this is definitely an odd response you’re seeing in the generated JSONL file. I work on the Shopify API Support team and was able to do a bit of digging into this on my end here for you. I attempted to replicate the Bulk Operations query using the image portion that you shared above:

images {
                  edges {
                    node {
                      id
                      originalSrc
                    }
                  }
                }

When I ran the Bulk Operation query on my end for the product images, I noticed that the OriginalSrc fields for the image’s URLS were surfaced/referenced correctly without that potential hash sum you mentioned appended to them in my JSONL file.

Would you be able to share the full body of the BulkOperationRunQuery call you’re making (with merchant information removed) that the shared image portion is apart of as well as the Request ID from that call? Having that information (particularly the Request ID from the response header) would allow us to try to replicate this exactly and retrieve logs to see if we can narrow down what caused those numbers to be appended to the end of the image URL/why it seemed time-limited.

Hope to hear back from you soon - let us know if we can clarify anything by replying directly to this thread. If you’d prefer to speak over email (if there is sensitive merchant information relevant to the API call, etc.) you can use our Issue Report Form to get in touch with us that way.

Thanks again for bringing this up - more than happy to dig into this further with you as based on my testing so far, this doesn’t seem to be an expected behaviour of our GraphQL Admin API.

Cheers.

@kchan @Alan_19 Was the issue resolved for you? We now have the exact same issue with some of our clients. The returned image URLs are attached with weird UUID attached to them causing it to return 404.