Graphql Mutation inventorySetOnHandQuantities not working

Topic summary

Issue: inventorySetOnHandQuantities GraphQL mutation updates the on_hand quantity incorrectly for a specific InventoryItem at a location. Setting quantity to K consistently results in on_hand = K–1. An initial attempt to set 3 returned no userErrors but inventoryAdjustmentGroup = null; later attempts show an adjustment group but still reflect K–1.

Context: Other items at the same location update correctly. No committed or reserved quantities exist. trackedEditable.locked = false (no lock reason). Adjustment history shows the expected new quantity (e.g., 3), but the Shopify Admin Product Editor displays the old on_hand (e.g., 2), suggesting API–UI desynchronization.

Support guidance: Could not reproduce on test store; notes the mutation cannot update locations owned by other apps’ fulfillment services. Requested a Partner Dashboard support ticket with store/app details and a recent timestamp for a failed update to investigate store-specific behavior.

Community input: One participant with a similar issue suggests removing the “inventoryLevels” reference and using the REST endpoint inventory_levels/set.json (available field) as a workaround.

Status: Unresolved/ongoing. Action item: submit a Partner Dashboard support request; consider REST workaround in the interim.

Summarized with AI on January 19. AI used: gpt-5.

Dear support,

We try to use inventorySetOnHandQuantities mutation to update on_hand quantity at location for specific InventoryItem “gid://shopify/InventoryItem/45703524974810” in our shop “gid://shopify/Shop/55075799231”:

https://shopify.dev/docs/api/admin-graphql/2023-07/mutations/inventorySetOnHandQuantities

Initial on_hand quantity is 2 as reported by query:

{
inventoryItem(id:“gid://shopify/InventoryItem/45703524974810”){
id
inventoryLevels(first:10){
edges{
node{
id
quantities(names:[
“available”, “committed”, “damaged”, “incoming”,
“on_hand”, “quality_control”, “reserved”,
“safety_stock”])
{
name
quantity
updatedAt
}
location{
id
}
}
}
}
}
}

Response

{
“data”: {
“inventoryItem”: {
“id”: “gid://shopify/InventoryItem/45703524974810”,
“inventoryLevels”: {
“edges”: [
{
“node”: {
“id”: “gid://shopify/InventoryLevel/95432802495?inventory_item_id=45703524974810”,
“quantities”: [
{
“name”: “available”,
“quantity”: 2,
“updatedAt”: “2023-07-21T03:43:45Z”
},
{
“name”: “committed”,
“quantity”: 0,
“updatedAt”: “2023-07-18T13:32:22Z”
},
{
“name”: “damaged”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “incoming”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “on_hand”,
“quantity”: 2,
“updatedAt”: “2023-07-21T03:43:45Z”
},
{
“name”: “quality_control”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “reserved”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “safety_stock”,
“quantity”: 0,
“updatedAt”: null
}
],
“location”: {
“id”: “gid://shopify/Location/61122379967”
}
}
}
]
}
}
},
“extensions”: {
“cost”: {
“requestedQueryCost”: 33,
“actualQueryCost”: 6,
“throttleStatus”: {
“maximumAvailable”: 1000,
“currentlyAvailable”: 994,
“restoreRate”: 50
}
}
}
}

When trying to update on_hand quantity to 3 at location nothing is happening:

mutation inventorySetOnHandQuantities($input: InventorySetOnHandQuantitiesInput!) {
inventorySetOnHandQuantities(input: $input) {
userErrors {
field
message
}
inventoryAdjustmentGroup {
createdAt
reason
changes {
item {
inventoryLevels(first: 10) {
edges {
node {
id
quantities(
names: [“available”, “committed”, “damaged”, “incoming”, “on_hand”, “quality_control”, “reserved”, “safety_stock”]
) {
name
quantity
updatedAt
}
location {
id
}
}
}
}
}
}
}
}
}

variables:

{“input”:{“reason”:“correction”,“setQuantities”:[{“inventoryItemId”:“gid://shopify/InventoryItem/45703524974810”,“locationId”:“gid://shopify/Location/61122379967”,“quantity”:3}]}}

Response:

{
“data”: {
“inventorySetOnHandQuantities”: {
“userErrors”: ,
“inventoryAdjustmentGroup”: null
}
},
“extensions”: {
“cost”: {
“requestedQueryCost”: 44,
“actualQueryCost”: 10,
“throttleStatus”: {
“maximumAvailable”: 1000,
“currentlyAvailable”: 990,
“restoreRate”: 50
}
}
}
}

Please help us to debug because no quantity update is happening.

Hi @shopyapp ,

That inventorySetOnHandQuantities mutation works on my test store, but can you update other inventory items at that location, or that inventory item at other locations?

I can’t replicate any issues with updating physical locations, or my own app’s third party fulfillment service, however the mutation will not allow me to update the inventory levels at locations belonging to other apps’ fulfillment services.

Hope that helps.

Hello,

Thank you for the answer, we sent all ID details in the hope that you will debug our instance. Is something special only about this InventoryItem / InventoryLevel.

On_hand quantity updates for all the other ProductVariants/InventoryItem/InventoryLevels quantities are working just fine at the same location.

After more tests we observed that: If we set quantity to 4 (instead of 3 as original mutation), the on_hand quantity will be updated to 3.

If we set on_hand quantity to 5, the on_hand quantity will be updated to 4.

So the update mutation has all access right to execute, but the result is wrong.

As you can see we don’t have any reserved or committed quantity for this product and always when we set on_hand quantity to K we will receive updated on_hand to K-1.

Mutation

mutation inventorySetOnHandQuantities($input: InventorySetOnHandQuantitiesInput!) {
inventorySetOnHandQuantities(input: $input) {
userErrors {
field
message
}
inventoryAdjustmentGroup {
createdAt
reason
changes {
item {
inventoryLevels(first: 10) {
edges {
node {
id
quantities(
names: [“available”, “committed”, “damaged”, “incoming”, “on_hand”, “quality_control”, “reserved”, “safety_stock”]
) {
name
quantity
updatedAt
}
location {
id
}
}
}
}
}
}
}
}
}

With variables:

{
“input”: {
“reason”: “correction”,
“setQuantities”: [
{
“inventoryItemId”: “gid://shopify/InventoryItem/45703524974810”,
“locationId”: “gid://shopify/Location/61122379967”,
“quantity”: 5
}
]
}
}

Produce result:

{
“data”: {
“inventorySetOnHandQuantities”: {
“userErrors”: ,
“inventoryAdjustmentGroup”: {
“createdAt”: “2023-07-21T12:52:56Z”,
“reason”: “correction”,
“changes”: [
{
“item”: {
“inventoryLevels”: {
“edges”: [
{
“node”: {
“id”: “gid://shopify/InventoryLevel/95432802495?inventory_item_id=45703524974810”,
“quantities”: [
{
“name”: “available”,
“quantity”: 4,
“updatedAt”: “2023-07-21T12:52:56Z”
},
{
“name”: “committed”,
“quantity”: 0,
“updatedAt”: “2023-07-18T13:32:22Z”
},
{
“name”: “damaged”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “incoming”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “on_hand”,
“quantity”: 4,
“updatedAt”: “2023-07-21T12:52:56Z”
},
{
“name”: “quality_control”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “reserved”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “safety_stock”,
“quantity”: 0,
“updatedAt”: null
}
],
“location”: {
“id”: “gid://shopify/Location/61122379967”
}
}
}
]
}
}
},
{
“item”: {
“inventoryLevels”: {
“edges”: [
{
“node”: {
“id”: “gid://shopify/InventoryLevel/95432802495?inventory_item_id=45703524974810”,
“quantities”: [
{
“name”: “available”,
“quantity”: 4,
“updatedAt”: “2023-07-21T12:52:56Z”
},
{
“name”: “committed”,
“quantity”: 0,
“updatedAt”: “2023-07-18T13:32:22Z”
},
{
“name”: “damaged”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “incoming”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “on_hand”,
“quantity”: 4,
“updatedAt”: “2023-07-21T12:52:56Z”
},
{
“name”: “quality_control”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “reserved”,
“quantity”: 0,
“updatedAt”: null
},
{
“name”: “safety_stock”,
“quantity”: 0,
“updatedAt”: null
}
],
“location”: {
“id”: “gid://shopify/Location/61122379967”
}
}
}
]
}
}
}
]
}
}
},
“extensions”: {
“cost”: {
“requestedQueryCost”: 44,
“actualQueryCost”: 23,
“throttleStatus”: {
“maximumAvailable”: 1000,
“currentlyAvailable”: 977,
“restoreRate”: 50
}
}
}
}

We hope this info will help for debugging.

Thank you

Dear @ShopifyDevSup ,

The trackedEditable is not locked.

We checked by query:

{
inventoryItem(id: “gid://shopify/InventoryItem/45703524974810”) {
id
trackedEditable {
locked
reason
}
inventoryLevels(first: 10) {
edges {
node {
id
}
}
}
}
}

With response:

{
“data”: {
“inventoryItem”: {
“id”: “gid://shopify/InventoryItem/45703524974810”,
“trackedEditable”: {
“locked”: false,
“reason”: null
},
“inventoryLevels”: {
“edges”: [
{
“node”: {
“id”: “gid://shopify/InventoryLevel/95432802495?inventory_item_id=45703524974810”
}
}
]
}
}
},
“extensions”: {
“cost”: {
“requestedQueryCost”: 14,
“actualQueryCost”: 5,
“throttleStatus”: {
“maximumAvailable”: 1000,
“currentlyAvailable”: 995,
“restoreRate”: 50
}
}
}
}

Is really strange because in Adjustment history we see the latest on_hand quantity correct (3):

Date Activity Committed Available On hand
27 minutes ago Inventory correction ShopyApp no change — increased by 2 for a total of 3 (+2)3 increased by 2 for a total of 3 (+2)3

But in Shopify Admin Product Editor we have on_hand displayed wrong (2).

Location
Committed Available On hand
0 2 2

Is like api GraphQL is in desync with Shopify Admin Product Editor user interface.

Can you please let us help you to debug and fix this Shopify bug?

Thank you

Hi @shopyapp ,

To enable further store specific investigation and more private communication, please submit a support request through the Partner Dashboard using the API Email us option, including a link to this forum post, which store and app are involved, as well as a date/time/timezone in the past 7 days when the quantity update via API didn’t work as expected.

Thanks and have a great day,
Jon551

I had a similar problem and the issue turned out to be the “inventoryLevels” reference. For some reason, you need to remove that reference. This has to be the only spot on the API with this structure. Below is the CURL example.

curl -d '{"location_id":1234,"inventory_item_id":"1234","available":42}' \
-X POST "https://STORE.myshopify.com/admin/api/2023-04/inventory_levels/set.json" \
-H "X-Shopify-Access-Token: TOKEN" \
-H "Content-Type: application/json"