Making idempotency mandatory for inventory adjustments and refund mutations

This changelog relates to concurrency protection features.


This is a companion discussion topic for the original entry at https://shopify.dev/changelog/making-idempotency-mandatory-for-inventory-adjustments-and-refund-mutations

I have tried the following queries via the 2026-04 Admin GraphQL endpoint, one with and one without an idempotency directive. I ran both queries 3 times.

My expectation was the following:

  • The query with the idempotency directive would result in one successful adjustment and 2 failed adjustments. This is based on the assumption that, because I did not update the idempotency key value, the second and third request would be rejected as duplicates
  • The query without the directive would result in no successful adjustments since it does not contain the required idempotency directive.

The actual results were 3 successful adjustments for both queries.

Query 1 with idempotency

mutation InventoryAdjustWithIdempotency($input: InventoryAdjustQuantitiesInput!) {
  inventoryAdjustQuantities(input: $input)  
  @idempotent(key: "3f5b6ebf-143c-4da5-8d0f-fb8553bfd85d") {
    inventoryAdjustmentGroup {
      id
      reason
      referenceDocumentUri
      changes(quantityNames: ["available"]) {
        name
        delta
        quantityAfterChange
      }
    }
    userErrors {
      field
      message
    }
  }
}

Query 2, no idempotency directive

mutation InventoryAdjustWithoutIdempotency($input: InventoryAdjustQuantitiesInput!) {
  inventoryAdjustQuantities(input: $input) {
    inventoryAdjustmentGroup {
      id
      reason
      referenceDocumentUri
      changes(quantityNames: ["available"]) {
        name
        delta
        quantityAfterChange
      }
    }
    userErrors {
      field
      message
    }
  }
}

I supplied valid variables each time:

{
  "input": {
    "name": "available",
    "reason": "correction",
    "changes": [
      {
        "delta": 4,
        "changeFromQuantity": null,
        "inventoryItemId": "gid://shopify/InventoryItem/xxx",
        "locationId": "gid://shopify/Location/xxx"
      }
    ]
  }
}

What am I missing? This does not seem to make sense given the docs. I also tried this on the 2026-01 endpoint with the same results, although I expected the same results for the second query since 2026-01 does not require the directive.

Just sharing here in case anyone comes across this same behaviour that @lrotherfield is reporting here.

We are discussing this behaviour further in the separate thread, if anyone else is experiencing this and has further questions, please feel free to post in the following thread:

1 Like