productSet mutation does not update alt text when originalSource is an external URL

Overview

When using the productSet mutation with the files input, the alt text is not updated if originalSource points to an external URL (e.g., Google Cloud Storage). However, the same mutation does update alt when originalSource points to a Shopify CDN URL.

We believe this is a bug or undocumented behavioral difference in the API.


Environment

  • API version: 2026-01
  • Mutation: productSet (synchronous: true)

What works

When originalSource is a Shopify CDN URL, alt is correctly updated:

Request:

mutation {
  productSet(synchronous: true, identifier: { id: "gid://shopify/Product/..." }, input: {
    files: [{
      filename: "index_main02_fw2024.jpg"
      originalSource: "https://cdn.shopify.com/s/files/.../index_main02_fw2024.jpg?v=..."
      alt: "A red winter jacket on a white background"
      contentType: IMAGE
      duplicateResolutionMode: REPLACE
    }]
  }) {
    product {
      images(first: 1) { nodes { altText } }
    }
  }
}

Response:

{
  "images": {
    "nodes": [{ "altText": "A red winter jacket on a white background" }]
  }
}

:white_check_mark: alt is updated correctly.


What does NOT work

When originalSource is an external URL (e.g., Google Cloud Storage), alt is not updated even though the file itself is replaced:

Request:

mutation {
  productSet(synchronous: true, identifier: { ... }, input: {
    files: [{
      filename: "product-image.webp"
      originalSource: "https://storage.googleapis.com/my-bucket/.../product-image.webp"
      alt: "A red winter jacket on a white background"
      contentType: IMAGE
      duplicateResolutionMode: REPLACE
    }]
  }) {
    product {
      images(first: 1) { nodes { altText } }
    }
  }
}

Response:

{
  "images": {
    "nodes": [{ "altText": "Previous alt text (not updated)" }]
  }
}

:cross_mark: alt is not updated. The old value remains.

Note: The image URL’s version parameter (?v=...) does change in the response, confirming that the file content itself was replaced from the external source. Only the alt text is not applied.


Root cause hypothesis

It appears that when originalSource is an external URL, Shopify processes the file as a new upload (download from external → re-upload). During this process, the alt field in FileSetInput is not applied to the resulting media. When originalSource is a Shopify CDN URL, Shopify treats it as a reference to an existing file and applies alt as a metadata update — which works correctly.


Why fileUpdate is not a viable workaround for us

We use productSet as a single atomic sync operation in our ERP system. Adding a separate fileUpdate call introduces partial failure risks and additional complexity that we would like to avoid.


Request

Could you please confirm whether this is intended behavior or a bug? If it is by design, could you document the distinction between Shopify CDN URLs and external URLs in the FileSetInput documentation?

Ideally, we would like alt to be applied consistently regardless of whether originalSource is a Shopify CDN URL or an external URL.

1 Like

Hi @tokujirou,

I can confirm that this is a known issue that our developers are currently aware of and looking into fixing further at this time.

Specifically the issue is that the Alt text is not respected in the productSet FileSetInput argument, if duplicateResolutionMode is set to REPLACE and an existing image with the file name already exists.

In this case as a workaround I would recommend changing your mutation input, setting duplicateResolutionMode: APPEND_UUID, and it will still behave as you are expecting it to.

Since productSet is a destructive mutation, meaning that any files not included in the fileSetInput array will be deleted, leaving only the files that you specify in the mutation itself.

Essentially it will delete the old image with the product-image.webp file name and the old alt text, then create a new product-image.webp image with the new image file and the new alt text.

Hi @Kellan-Shopify ,

Thank you for the detailed explanation — this was very helpful.

We will review this on our side and check whether using this workaround is safe for our product.
Since this is a known issue, we are looking forward to it being resolved soon.

Thank you again for the clarification!

1 Like