productSet Mutation with duplicateResolutionMode: REPLACE Causes Images to Disappear Every Other Time

Hi all,

I’ve run into an odd issue when using the productSet mutation with images and duplicateResolutionMode: REPLACE.

The first time I run the mutation, everything works fine — the product is created and the images show up as expected:


The second time I run the exact same mutation, the same product stays/updates but the images disappear:


The third time, the images come back:

(Shopify dev community forum has a limit of up to 5 images that can be attached to a post, so you can view the other 2 images at the links below)

GraphQL Query RUN #3 - files reappear
https://cdn.shopify.com/s/files/1/0878/3799/9398/files/Screenshot_2025-05-01_at_9.12.41_AM.png?v=1746107020

GraphQL Query RUN #3 - main product image reappears
https://cdn.shopify.com/s/files/1/0878/3799/9398/files/Screenshot_2025-05-01_at_9.12.24_AM.png?v=1746107020

This keeps repeating — images show up on odd runs, disappear on even runs.

Here is the GraphQL query that was used:

Query

mutation createProductWMedia($identifier: ProductSetIdentifiers!, $productSet: ProductSetInput!, $synchronous: Boolean!) {
  productSet(
    identifier: $identifier
    synchronous: $synchronous
    input: $productSet
  ) {
    product {
      title
      id
      US: publishedInContext(context: {country: US})
      CA: publishedInContext(context: {country: CA})
      AU: publishedInContext(context: {country: AU})
    }
    productSetOperation {
      id
      status
      userErrors {
        code
        field
        message
      }
    }
    userErrors {
      code
      field
      message
    }
  }
}

Variables:

{
  "identifier": {
    "customId": {
      "namespace": "custom",
      "key": "external_system_id",
      "value": "1000000001-CAMERA"
    }
  },
  "synchronous": true,
  "productSet": {
    "descriptionHtml": "",
    "title": "Cool New Camera",
    "handle": "cool-new-camera",
    "files": [
      {
        "filename": "black-camera.jpg",
        "contentType": "IMAGE",
        "alt": "Black camera",
        "duplicateResolutionMode": "REPLACE",
        "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/black-camera.jpg"
      },
      {
        "filename": "blue-camera.jpg",
        "contentType": "IMAGE",
        "alt": "Blue camera",
        "duplicateResolutionMode": "REPLACE",
        "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/blue-camera.jpg"
      }
    ],
    "productOptions": [
      {
        "name": "Color",
        "values": [
          {
            "name": "Black"
          },
          {
            "name": "Blue"
          }
        ]
      }
    ],
    "variants": [
      {
        "optionValues": [
          {
            "optionName": "Color",
            "name": "Black"
          }
        ],
        "sku": "GTS-002",
        "file": {
          "filename": "black-camera.jpg",
          "contentType": "IMAGE",
          "alt": "Black camera",
          "duplicateResolutionMode": "REPLACE",
          "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/black-camera.jpg"
        }
      },
      {
        "optionValues": [
          {
            "optionName": "Color",
            "name": "Blue"
          }
        ],
        "sku": "GTS-777",
        "file": {
          "filename": "blue-camera.jpg",
          "contentType": "IMAGE",
          "alt": "Blue camera",
          "duplicateResolutionMode": "REPLACE",
          "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/blue-camera.jpg"
        }
      }
    ]
  }
}

Response:

{
  "data": {
    "productSet": {
      "product": {
        "title": "Cool New Camera",
        "id": "gid://shopify/Product/10106483638566",
        "US": true,
        "CA": true,
        "AU": true
      },
      "productSetOperation": null,
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 51,
      "actualQueryCost": 50,
      "throttleStatus": {
        "maximumAvailable": 20000,
        "currentlyAvailable": 19950,
        "restoreRate": 1000
      }
    }
  }
}

Furthermore, there is another strange issue. When you view the product details for that product in Shopify admin, the product still shows a grayed-out media thumbnail that looks like it’s trying to reference images—but nothing can be clicked. It appears the media is left in an incomplete or broken state:

Some extra details:

  • To avoid any cyclic dependency of image references, I’m using public image URLs hosted on a different Shopify store, not the one where I ran the above mutation on. I also tried images hosted somewhere else other than Shopify and noticed the same issue.
  • I made sure the filenames are clean and simple: black-camera.jpg and blue-camera.jpg.
  • No special characters, weird formatting, or anything like that.
  • In an attempt to isolate the issue, when I use the fileCreate mutation instead, everything works consistently — the images are always replaced as expected, no matter how many times I run the GraphQL query like below:
    Query:
mutation fileCreate($files: [FileCreateInput!]!) {
  fileCreate(files: $files) {
    files {
      id
      fileStatus
      alt
      createdAt
    }
    userErrors {
      code
      message
    }
  }
}

Variables:

{
  "files": [
    {
      "filename": "black-camera.jpg",
      "contentType": "IMAGE",
      "alt": "Black camera",
      "duplicateResolutionMode": "REPLACE",
      "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/black-camera.jpg"
    },
    {
      "filename": "blue-camera.jpg",
      "contentType": "IMAGE",
      "alt": "Blue camera",
      "duplicateResolutionMode": "REPLACE",
      "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/blue-camera.jpg"
    }
  ]
}

Result:

{
  "data": {
    "fileCreate": {
      "files": [
        {
          "id": "gid://shopify/MediaImage/42177687716134",
          "fileStatus": "READY",
          "alt": "Black camera",
          "createdAt": "2025-05-01T13:12:11Z"
        },
        {
          "id": "gid://shopify/MediaImage/42177687748902",
          "fileStatus": "READY",
          "alt": "Blue camera",
          "createdAt": "2025-05-01T13:12:11Z"
        }
      ],
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 20,
      "actualQueryCost": 20,
      "throttleStatus": {
        "maximumAvailable": 20000,
        "currentlyAvailable": 19980,
        "restoreRate": 1000
      }
    }
  }
}

So this issue appears to be isolated to the productSet mutation. Would someone from Shopify Staff please take a look and let me know?

Thank you for your time!

:eyes: On first sight this looks similar to ProductSet Mutation Issue: Images are Deleted or Restored with Each Mutation Execution

Hey @Kevin_Sieger , thanks I already checked that one, and you’re right it is similar. However when I started working on writing it up, I didn’t see that issue:
Anyways, I tried including the mediaWarnings and mediaErrors but its behaving in the same way in alternating responses:

Looks like the response just alternates between

{
  "data": {
    "productSet": {
      "product": {
        "title": "Cool New Camera",
        "id": "gid://shopify/Product/10106804273446",
        "US": true,
        "CA": true,
        "AU": true,
        "media": {
          "nodes": []
        }
      },
      "productSetOperation": null,
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 65,
      "actualQueryCost": 52,
      "throttleStatus": {
        "maximumAvailable": 20000,
        "currentlyAvailable": 19948,
        "restoreRate": 1000
      }
    }
  }
}

and

{
  "data": {
    "productSet": {
      "product": {
        "title": "Cool New Camera",
        "id": "gid://shopify/Product/10106804273446",
        "US": true,
        "CA": true,
        "AU": true,
        "media": {
          "nodes": [
            {
              "id": "gid://shopify/MediaImage/42179317399846",
              "mediaWarnings": [],
              "mediaErrors": [],
              "mediaContentType": "IMAGE"
            },
            {
              "id": "gid://shopify/MediaImage/42179317432614",
              "mediaWarnings": [],
              "mediaErrors": [],
              "mediaContentType": "IMAGE"
            }
          ]
        }
      },
      "productSetOperation": null,
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 65,
      "actualQueryCost": 55,
      "throttleStatus": {
        "maximumAvailable": 20000,
        "currentlyAvailable": 19945,
        "restoreRate": 1000
      }
    }
  }
}

Would someone from Shopify be able to take a look?

1 Like

Hey @brill , this looks very similar to this post here: Uploading Product Images Unexpected Behaviour

Have you attempted to add the mediaStatus field alongside the warnings and errors?

Since you are seeing greyed out images, if you query the product media separately does anything return?

Hey @KyleG-Shopify , I am outputting the media status field as well as the mediaErrors and mediaWarnings fields. It’s still doing the same alternating thing:

Request

mutation createProductWMedia($identifier: ProductSetIdentifiers!, $productSet: ProductSetInput!, $synchronous: Boolean!) {
  productSet(
    identifier: $identifier
    synchronous: $synchronous
    input: $productSet
  ) {
    product {
      title
      id
      US: publishedInContext(context: {country: US})
      CA: publishedInContext(context: {country: CA})
      AU: publishedInContext(context: {country: AU})
      media(first:10) {
        nodes {
          id
          mediaWarnings {
            code
            message
          }
          mediaErrors {
            code
            message
          }
          mediaContentType
        }
      }
      variants(first:10) {
        nodes {
          media(first:10) {
            nodes {
              status
              id
              mediaErrors {
                code
                details
                message
              }
              mediaWarnings {
                code
                message
              }
              mediaContentType
            }
          }
        }
      }
    }
    productSetOperation {
      id
      status
      userErrors {
        code
        field
        message
      }
    }
    userErrors {
      code
      field
      message
    }
  }
}

Variables:

{
  "identifier": {
    "customId": {
      "namespace": "custom",
      "key": "external_system_id",
      "value": "1000000001-CAMERA"
    }
  },
  "synchronous": true,
  "productSet": {
    "descriptionHtml": "",
    "title": "Cool New Camera",
    "files": [
      {
        "filename": "black-camera.jpg",
        "contentType": "IMAGE",
        "alt": "Black camera",
        "duplicateResolutionMode": "REPLACE",
        "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/black-camera.jpg"
      },
      {
        "filename": "blue-camera.jpg",
        "contentType": "IMAGE",
        "alt": "Blue camera",
        "duplicateResolutionMode": "REPLACE",
        "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/blue-camera.jpg"
      }
    ],
    "productOptions": [
      {
        "name": "Color",
        "values": [
          {
            "name": "Black"
          },
          {
            "name": "Blue"
          }
        ]
      }
    ],
    "variants": [
      {
        "optionValues": [
          {
            "optionName": "Color",
            "name": "Black"
          }
        ],
        "sku": "GTS-002",
        "file": {
          "filename": "black-camera.jpg",
          "contentType": "IMAGE",
          "alt": "Black camera",
          "duplicateResolutionMode": "REPLACE",
          "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/black-camera.jpg"
        }
      },
      {
        "optionValues": [
          {
            "optionName": "Color",
            "name": "Blue"
          }
        ],
        "sku": "GTS-777",
        "file": {
          "filename": "blue-camera.jpg",
          "contentType": "IMAGE",
          "alt": "Blue camera",
          "duplicateResolutionMode": "REPLACE",
          "originalSource": "https://cdn.shopify.com/s/files/1/0716/7279/1289/files/blue-camera.jpg"
        }
      }
    ]
  }
}

Response after RUN 1:
X-Request-Id: b72e4ec3af4cfb2d4a6755a91d4204de
X-Upstream-Request-Id: 38017144-fffb-45eb-a487-21f85ca485aa-1746132972
Response:

{
  "data": {
    "productSet": {
      "product": {
        "title": "Cool New Camera",
        "id": "gid://shopify/Product/10106804273446",
        "US": true,
        "CA": true,
        "AU": true,
        "media": {
          "nodes": [
            {
              "id": "gid://shopify/MediaImage/42179738927398",
              "mediaWarnings": [],
              "mediaErrors": [],
              "mediaContentType": "IMAGE"
            },
            {
              "id": "gid://shopify/MediaImage/42179738960166",
              "mediaWarnings": [],
              "mediaErrors": [],
              "mediaContentType": "IMAGE"
            }
          ]
        },
        "variants": {
          "nodes": [
            {
              "media": {
                "nodes": [
                  {
                    "status": "UPLOADED",
                    "id": "gid://shopify/MediaImage/42179738927398",
                    "mediaErrors": [],
                    "mediaWarnings": [],
                    "mediaContentType": "IMAGE"
                  }
                ]
              }
            },
            {
              "media": {
                "nodes": [
                  {
                    "status": "UPLOADED",
                    "id": "gid://shopify/MediaImage/42179738960166",
                    "mediaErrors": [],
                    "mediaWarnings": [],
                    "mediaContentType": "IMAGE"
                  }
                ]
              }
            }
          ]
        }
      },
      "productSetOperation": null,
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 127,
      "actualQueryCost": 60,
      "throttleStatus": {
        "maximumAvailable": 20000,
        "currentlyAvailable": 19940,
        "restoreRate": 1000
      }
    }
  }
}

Response after RUN 2:
X-Request-Id: 2439d27d8bd8704644e62ecc391dcb36
X-Upstream-Request-Id: beae9346-bfe5-4b07-84e7-bd25f193ea33-1746133100
Response:

{
  "data": {
    "productSet": {
      "product": {
        "title": "Cool New Camera",
        "id": "gid://shopify/Product/10106804273446",
        "US": true,
        "CA": true,
        "AU": true,
        "media": {
          "nodes": []
        },
        "variants": {
          "nodes": [
            {
              "media": {
                "nodes": []
              }
            },
            {
              "media": {
                "nodes": []
              }
            }
          ]
        }
      },
      "productSetOperation": null,
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 127,
      "actualQueryCost": 57,
      "throttleStatus": {
        "maximumAvailable": 20000,
        "currentlyAvailable": 19943,
        "restoreRate": 1000
      }
    }
  }
}

Thanks. I’ve been testing here and I haven’t been able to replicate. I’ll see if I can find something in the logs from that request id.

Example of my request here:

  productSet(synchronous: $synchronous, input: $productSet) {
    product {
      id
      media(first: 5) {
        nodes {
          id          
          alt
          mediaContentType
          status
        }
      }
      variants(first: 5) {
        nodes {
          title
          price          
        }
      }
    }
    userErrors {
      field
      message
    }
  }
}

Variables:

{
  "synchronous": true,
  "productSet": {
    "id": "gid://shopify/Product/10588692086806",
    "title": "Fancy Hats",
    "productOptions": [
      {
        "name": "Color",
        "position": 1,
        "values": [
          {
            "name": "Grey"
          },
          {
            "name": "Black"
          }
        ]
      }
    ],
    "files": [
      
      {
        "originalSource": "https://burst.shopifycdn.com/photos/bearded-man-in-sun-and-shadow.jpg",
        "alt": "An elegant black hat",
        "filename": "bearded-man-in-sun-and-shadow.jpg",
        "contentType": "IMAGE",
        "duplicateResolutionMode": "REPLACE"
      }
    ],
    "variants": [
      {
        "optionValues": [
          {
            "optionName": "Color",
            "name": "Grey"
          }
        ],
        
        "price": 11.99
      },
      {
        "optionValues": [
          {
            "optionName": "Color",
            "name": "Black"
          }
        ],
        
        "price": 11.99
      }
    ]
  }
}

Okay @KyleG-Shopify really strange. Only today, once I tried changing the identifier portion of the variables from

"identifier": {
    "customId": {
      "namespace": "custom",
      "key": "external_system_id",
      "value": "1000000001-CAMERA"
    }
  }

to

"identifier": {
    "customId": {
      "namespace": "custom",
      "key": "external_system_id",
      "value": "1000000001-CAMERA5" // <--appended a 5 at the end of the ID
    }
  }

It went and created a new product (as expected), but now it’s working! No matter how many times I hit the query that issue of the images appearing and disappearing is no longer there. So I thought, maybe it was that one product that was corrupt.
BUT - then, when I went back to re-update the other product with the old identifier…

"identifier": {
    "customId": {
      "namespace": "custom",
      "key": "external_system_id",
      "value": "1000000001-CAMERA"
    }
  }

It also started working again! Either some fix was done in the past day, or some weird behavior put the products/media in a weird unrecoverable state until creating a new product with the productSet mutation put it back in order…I am still perplexed.

In the meantime can you please check the request ID on your end to see what may have happened that caused that fluke?

I would appreciate it so much, thanks!

Hello,

This is still happening for me.

@KyleG-Shopify have you got any updates? Or any suggestions on a better method?

Thank you

Hey @edstevo

Our team has identified an issue here and are currently working on a fix. I’ll update you as soon as it’s in place.

1 Like

Hey everyone,

This issue should be resolved now. If you’re still seeing unexpected behaviour, let me know!