Problems setting read-only metafields in async ProductSet

I’m running into issues trying to set read-only read-only metafields in asynchronous ProductSet calls.

For background:

  • API version is 2025-10.
  • ID Metafield definition exists and allows us to use ProductSet to insert/update (upsert) in a single operation.
  • I’m using bulk operations on files comprised of multiple records in JSONL format.
  • Files are uploaded, the mutation is run, and I’m waiting for the bulk operation to finish.
  • I can’t get the “metafields” property to work.

Here’s an example record from the file:

{"identifier":{"customId":{"key":"id","value":"1632"}},"input":{"title":"Product #1632","metafields":[{"key":"brand","value":"ACME"}]}}

Here’s the mutation:

mutation call($identifier: ProductSetIdentifiers, $input: ProductSetInput!) { productSet(identifier: $identifier, input: $input) { product { id } userErrors { code message field } } }

Here’s the complete response I get:

{"data":{"productSet":{"product":null,"userErrors":[{"code":"METAFIELD_MISMATCH","message":"The input argument `metafields` (if present) must contain the `customId` value.","field":["input"]}]}},"__lineNumber":0}

I’ve tried adding a “customId” node to the metafield:

{"identifier":{"customId":{"key":"id","value":"1632"}},"input":{"title":"Product #1632","metafields":[{"customId":{"key":"brand","value":"ACME"}}]}}

And I get this error:

{"data":{"bulkOperationRunMutation":{"bulkOperation":null,"userErrors":[{"message":"Invalid Bulk Mutation Field - Variable $input of type ProductSetInput! was provided invalid value for metafields.0.customId (Field is not defined on MetafieldInput)","field":null}]}},"extensions":{"cost":{"requestedQueryCost":10,"actualQueryCost":10,"throttleStatus":{"maximumAvailable":2000.0,"currentlyAvailable":1990,"restoreRate":100.0}}}}

There is zero documentation available indicating:

  • How to use a “customId” (UniqueMetafieldValueInput) node on the MetafieldInput object.
  • How to resolve METAFIELD_MISMATCH errors on the ProductSet async call.

The error indicates this should be possible. I think I’m probably missing something in the mutation definition… but I’m currently at a loss.

Note: I’m not looking to just set product-level metafields. I’ve created read-only, pinned product-level metafield definitions that are visible in the admin. The “id” metafield is being set properly and I want to set the other read-only metafields, as well.

Please let me know what I’m doing wrong!

Thanks in advance.

@Paige-Shopify You were extremely helpful re: another issue I posted a few weeks ago. Would it be possible to put this issue in front of someone who can help on the staff side?

1 Like

Hi again!

Thanks for reaching out :slight_smile:

I’ve replicated the errors you’re encountering to confirm you’re hitting a limitation with the ProductSet mutation when using customId identifiers:
When using customId as the identifier, productSet does not accept any metafields in the input.

The customId error appears to be returned because it is used for product identification but isn’t part of the MetafieldInput schema.

Workarounds

Option A) Use productSet without metafields + metafieldsSet (two-step approach)

Option B) Use the handle or id identifier instead in productSet

Option C) Use productCreate/productUpdate instead

You have a great point that this isn’t documented clearly. Thank you for sharing your feedback on this. We’ll work on getting this documented.

@Paige-Shopify ProductSet WILL accept metafields when custom id is used; just not metafield definitions. It will accept one-off metafields on that product, which can’t be set to read-only.

@AppDeveloper, I want to make sure I fully understand the issue you’re encountering so I can investigate this properly.

For context, I used the following tests to investigate this issue:

  1. Create metafield definition for custom.brand (type: single_line_text_field, access: storefront: PUBLIC_READ)

  2. productSet with customId id + custom.brand metafield

  • Error: METAFIELD_MISMATCH: "The input argument metafields(if present) must contain thecustomId value."
  1. productSet with customId id + customId field in custom.brand metafield
  • Error: "Variable $input of type ProductSetInput! was provided invalid value for metafields.0.customId (Field is not defined on MetafieldInput)
  1. productSet with customId id + undefined metafield with value matching id
  • Error: METAFIELD_MISMATCH: "The input argument metafields (if present) must contain the customId value."
  1. productSet with customId id + another undefined metafield but with unrelated value
  • Error: METAFIELD_MISMATCH: "The input argument metafields (if present) must contain the customId value."
  • Variables:
    identifier: {
            customId: {
              key: "id",
              value: "metafield-tests-id"
            }
          },
          input: {
            title: "Metafield Tests Product",
            metafields: [{
              namespace: "custom",
              key: "one_off_field", 
              value: "Test one-off value",
            }]
          }
  1. productSet with customId id + customId field in undefined metafield
  • Error: "Variable $input of type ProductSetInput! was provided invalid value for metafields.0.customId (Field is not defined on MetafieldInput)
  • Variables:
   identifier: {
            customId: {
              key: "id",
              value: "metafield-tests-id"
            }
          },
          input: {
            title: "Metafield Tests Product",
            metafields: [{
              namespace: "custom",
              key: "another_field", 
              value: "Test value",
              type: "single_line_text_field",
              customId: {
                key: "another_field",
                value: "test-another"
              }
            }]
          }
  1. All workarounds succeeded

Then confirmed internal documentation of my findings of the tests.

The results revealed that when using customId, the metafield operations fail.

Could you please share an example mutation and variables where you successfully set a one-off metafield using customId identifier?

@Paige-Shopify I’m embarrassed to say I think I was mistaken in my response to you. I’m unable to replicate my assertion, so we’re back to where we started: unable to set metafields when using a productSet operation with a customId.

Thank you for your effort trying to track this down - I appreciate it. I get what you’re saying, but the mutation response indicates it should be possible. I suspect it will be in a future implementation and this response may be bleeding into the 2025-10 version.

The workaround you’ve laid out are logical, but I’m not comfortable with them. Adding metafields during productSet should cost .4, so I think I’ll hold out for a while if/until this can implement metafields in this context. Can I submit a formal request for this functionality in a future version?

That’s alright!

Of course, I can put it this down as a feature request. Although I can’t confirm when/if it would be implemented. Happy to provide an update here once it has though :slight_smile:

Hi @AppDeveloper!

The issue is related to how productSet handles metafields as a list field.

When you include metafields in a productSet operation, the mutation replaces the entire metafields list with what you provide. This means any metafields not included in your input, including the ID metafield you’re using in the identifier, would be removed, which causes the METAFIELD_MISMATCH error.

The solution: Include your ID metafield in the metafields array using the standard key and value format (not customId, which isn’t part of the MetafieldInput schema).

Here’s what your record should look like:

{
  "identifier": {
    "customId": {
      "key": "id",
      "value": "1632"
    }
  },
  "input": {
    "title": "Product #1632",
    "metafields": [
      {
        "key": "id",
        "value": "1632"
      },
      {
        "key": "brand",
        "value": "ACME"
      }
    ]
  }
}

Notice that the ID metafield appears in both places: once in the identifier to locate the product, and again in the metafields array to ensure it’s retained.

This should resolve the error you’re seeing.

1 Like

@danloomer This is the correct solution!

I can confirm this works for setting metafields for multiple pinned, read-only definitions in a single ProductSet call. The list behavior is also correct, meaning that metafields are removed as expected.

The solution is a little obscure so I think a documentation update to METAFIELD_MISMATCHin this context would be helpful to others in the future.

Thanks again to you and @Paige-Shopify for your help.

1 Like

@AppDeveloper Glad it worked, and totally agreed!

I’ve passed on the feedback to clarify the error message and the documentation.

1 Like