← All articles

September 27, 2026 · Muhammad Rehan · More by Muhammad Rehan

Shopify's CANCELED Receive Needs Idempotent Retries

Shopify's new CANCELED receive action adds a third shipment outcome — but it needs retry logic that already handles the mandatory idempotency key.

On September 17, 2026, Shopify shipped a CANCELED receive action for the inventory shipments API, available on GraphQL Admin API version 2026-10 (and unstable). It sounds like a small addition — a new enum value — but it fixes a real gap for anyone reconciling Shopify inventory shipments against a 3PL, WMS, or ERP inbound receiving process: warehouses hit shipments that will never arrive constantly, and the old two-state model couldn't represent that outcome.

A third state, not a rename

Before this change, inventoryShipmentReceive only recognized accepted and rejected line items. A unit that was never going to show up had nowhere honest to go — it either got misrecorded as rejected or left permanently unreceived. The update adds totalCanceledQuantity on InventoryShipment and canceledQuantity on InventoryShipmentLineItem, plus a CANCELED value on InventoryShipmentReceiveLineItemReason that you can pass per line item or as a bulkReceiveAction.

The detail that will break assumptions in existing code: canceled units still count toward InventoryShipment.totalReceivedQuantity. On API version 2026-10, that total is no longer a simple accepted-plus-rejected split — it's accepted plus rejected plus canceled. Any reconciliation logic that assumed a two-way breakdown of totalReceivedQuantity needs to be updated to a three-way one, or it will misreport what actually happened to a shipment.

Webhooks change shape too. inventory_shipments/receive_items payloads on API version 2026-10+ gain old_canceled_quantity and new_canceled_quantity per item. And a receive that only changes canceled quantities now triggers a webhook delivery it previously wouldn't have — worth checking if your integration filters deliveries by what it considers a "meaningful" change. Apps still on pre-2026-10 API versions are unaffected: no new fields, no new enum value, and canceled-only receives stay suppressed.

Why this depends on idempotency you may already be skipping

The mutation example in Shopify's changelog shows @idempotent(key: "...") on inventoryShipmentReceive, with a note that the key has been required since API version 2026-04. That requirement didn't arrive with this change — it was announced December 12, 2025 and became mandatory in April 2026, alongside a batch of other inventory and refund mutations. If your integration is only now wiring up CANCELED handling, it's worth confirming your retry logic actually generates and reuses idempotency keys correctly, not just that the mutation runs.

Shopify tracks idempotency keys for 24 hours from the original request; after that, a retry is treated as a new operation. Two error codes matter for retry logic: IDEMPOTENCY_CONCURRENT_REQUEST, when another request with the same key is still processing, and IDEMPOTENCY_KEY_PARAMETER_MISMATCH, when the same key gets reused with different parameters. A retry loop that doesn't reuse the original key on failure — or that regenerates a key on every attempt — reopens the exact double-processing risk idempotency keys exist to close, now with a third outcome state to double-process.

Sources

Operations & Fulfillment

ASSOSIATIX works on this every day. See our Shopify Operations Automation service

$./start-project.sh

READY TO BUILD
WHAT'S NEXT?

Tell us where you are and where you want to go. We'll help you choose the right path—storefront, system, product, or a focused growth sprint.