Blog · 19 October 2026 · 8 min read

Reading the Shopify write log: every change Restock Ops made

Every quantity, cost and stocking change Restock Ops writes to Shopify is logged. What each row, status and reason means, and what to do when one fails.

Shopify is the only place your stock counts live. Restock Ops never keeps a quantity of its own; it reads from Shopify and, when you receive a delivery or apply a stocktake, it writes back. Every one of those writes goes through a single function that records what it is about to send, sends it, and records what Shopify answered. The result is the Shopify write log, and it is the first page to open when a number in Shopify does not match what you expected.

This post explains where the log is, what each row means, which Shopify reason code each kind of write carries, and how to use the log to settle an argument with a stock count. It is written from the code in Restock Ops rather than from a feature list, so the wording matches what you will see.

Where the log is

Open Settings. Below the Receiving and Reorder sections there is a section headed Shopify write log with a table of the fifty most recent writes, newest first. Each row has four columns: What, a one line summary of the write with Shopify's error message in red if there was one; Status, a badge reading succeeded, failed or pending; When; and Receipt, a link to the receipt the write belongs to, or a dash for stocktake and projection writes.

Each receipt page carries its own copy of the same information, limited to the writes made for that receipt, with the rows that were produced by an undo marked as such. The receipt page is the better view when you are looking at one delivery; Settings is the better view when you want to see everything the app has done this week.

One row per mutation, written before it is sent

The order of events matters for reading the log. When the app is about to change something in Shopify, it first inserts a row with the summary, the exact request it will send and a status of pending. Then it sends the request. If Shopify answers with a result, the row is updated to succeeded and Shopify's response is stored with it, including the id of the inventory adjustment group Shopify created. If Shopify answers with user errors, or the request fails outright, the row is updated to failed and the error text is stored.

Because the row exists before the request, a write can never happen without a trace. A row that stays pending for more than a few seconds means the app stopped between writing the row and hearing back, which in practice means a crash or a lost connection at exactly the wrong moment. It is rare; when it happens, compare the quantity in Shopify with the request and treat the row as unknown rather than as succeeded.

The row's own id is also sent to Shopify as the idempotency key of the mutation. If the same request were ever sent twice, because of a retry on a flaky connection for example, Shopify applies it once. That is why you will not see duplicate adjustments in Shopify's history even on a bad network day.

What the summaries mean

Write summaries, the kind of write behind them and the reason Shopify records
Summary (example)What it doesShopify reason
PO-1007 receipt #2: stock Ceramic Mug at WarehouseActivates the inventory item at the destination so it can hold stock there. Only for lines that were tracked but not yet stocked at that location.none (activation, not an adjustment)
PO-1007 receipt #2: +36 available at WarehouseOne adjustment covering every tracked line in the receipt, adding the received quantity to available. 36 is the sum across lines.received
PO-1007 receipt #2: remove received units from incomingOnly when the incoming projection setting is on: subtracts the received units from the incoming quantity the PO had projected.movement_received
PO-1007 receipt #2: cost Ceramic Mug 3.20 (arrow) 3.40Writes the new unit cost to the inventory item. One row per line whose cost changed; a dash before the arrow means the item had no cost yet.none (inventory item update)
PO-1007: project on-order units as incoming at WarehouseWhen a PO is marked ordered with projection on: adds outstanding units to incoming. The clear variant removes them on cancel, close or receipt completion.movement_created / movement_canceled
Stocktake "October count": 4 discrepancies at WarehouseApplies the counted differences to available in one adjustment.cycle_count_available
PO-1007 receipt #2: -36 available at WarehouseUndo of a receipt: the inverse quantity adjustment.correction
PO-1007 receipt #2: put units back on incomingUndo of a receipt with projection on: restores the incoming units.movement_updated
PO-1007 receipt #2: cost Ceramic Mug back to 3.20Undo of a receipt: restores the previous unit cost.none (inventory item update)
Undo stocktake "October count" at WarehouseReverses an applied stocktake in one adjustment.correction

The reasons in the right column are not the app's invention. They are the reason codes Shopify accepts on an inventory adjustment, and they are what Shopify shows in the adjustment history of a product, next to the app's name. Received, correction and cycle count are the ones a merchant reads most; the movement reasons belong to the incoming quantity and only appear if you use the incoming projection setting.

Every quantity adjustment also carries a reference document URI of the form restock-ops://your-store/receipts/the-receipt-id, or the equivalent for a purchase order or a stocktake. Shopify stores it with the adjustment group. It is not a clickable link in the Shopify admin, but it ties each adjustment to the exact receipt that caused it, which is what makes a reconciliation possible months later.

The order of writes in a receipt

A receipt with several lines produces several rows, always in the same order. First come the activations, one per line that needs one. Then a single available adjustment for all tracked lines together. Then, if projection is on, a single incoming adjustment reversing the received units. Then one cost write per line whose unit cost changed, each followed by a cost history entry inside the app. Lines whose inventory is not tracked in Shopify get no quantity write at all, but they still get a cost write if the cost changed, because the inventory item exists even when its quantity is not tracked.

If a receipt consists only of untracked lines, the available adjustment has nothing to send. The app still writes a row for it, with the suffix (nothing to change), status succeeded and an empty request. That row is there so the receipt's write list is complete; it is not an error.

When a row says failed

A failed row shows Shopify's own message in red after the summary, for example that an inventory item could not be found or that the location is not active. Two things follow from the way the sequence above runs. The receipt itself is already saved in the app by the time the writes start, so you will find it on the purchase order with a warning reading Shopify rejected a write, followed by the message and Check the write log. And the sequence stops at the first failure: writes that would have come after it in the order above were not attempted, so a failed available adjustment means the cost writes for that receipt did not happen either.

Nothing is retried automatically. The right sequence is to read the message, check the quantity in Shopify for the affected items, and fix the cause: reactivate the location, restore a deleted product, or whatever the message points at. Then either undo the receipt and receive it again, or correct the quantity by hand in Shopify if only one line is involved. The undo guide explains what undo reverses; be aware that undo issues inverse writes for the whole receipt, so on a receipt that half succeeded, check the result in Shopify afterwards.

Undo rows

Undo is available only on the most recent applied receipt of a purchase order, and on an applied stocktake. When you use it, the app does not delete anything from the log. It adds new rows, each linked to the row it reverses, with the correction and movement_updated reasons shown in the table. On the receipt page these rows are marked as undo rows so the pairs are easy to spot. In Shopify's adjustment history you will see the original adjustment and the inverse one, both attributed to the app, which is exactly the audit trail an accountant wants: nothing edited, everything reversed in the open.

Costs follow the same pattern. The undo writes the previous unit cost back and adds a cost history entry, so the cost history shows the cost going up on receipt and back down on undo, with both receipts named.

Using the log when a number looks wrong

  1. Note the product, the location and the quantity Shopify shows now, and roughly when it changed. Shopify's own adjustment history on the product page gives the time and the reason.
  2. Open Settings, Shopify write log, and find rows around that time for that location. The summary names the purchase order and receipt number, so you can open the receipt from the row.
  3. Compare the receipt's lines with what was actually delivered. If the receipt is right and Shopify is wrong, look for a failed or pending row: the quantity may never have been written.
  4. If the receipt is wrong, undo it if it is still the latest receipt on that PO, correct the quantities, and receive again. The log will show the inverse rows followed by the new ones.
  5. If neither the receipt nor the log explains the change, the adjustment did not come from Restock Ops. The reason and the app name in Shopify's history will point at the actual source: a POS sale, a manual edit, another app.

The log cannot be edited or cleared from the app, and it is deleted with everything else when the app is uninstalled and Shopify's data removal request arrives; export the receipts you need before that. While the app is installed, the log is the one place where every Shopify write it ever made can be found, which is the standard any app that touches your inventory should meet.

FAQ

Does the write log include quantity changes made by other apps or by staff in Shopify?

No. It lists only the writes Restock Ops sent. For everything else, use the adjustment history on the product page in Shopify, which names the app or staff member behind each change.

Why does a receipt show a (nothing to change) row?

Every receipt gets an available adjustment row. If none of its lines is tracked in Shopify, there is no quantity to send, so the row is recorded as succeeded with that suffix and no request. It keeps the receipt's write list complete.

A row is marked failed but the quantity in Shopify looks right. What happened?

Most likely someone corrected the quantity by hand after the failure, or the failed write was the incoming reversal rather than the available adjustment. Read the summary: it says which quantity and which receipt the row was for.

Can I retry a failed write from the log?

Not from the log itself. Fix the cause the error message points at, then undo the receipt and receive it again, or adjust the single affected quantity by hand in Shopify. Both leave a clear trail.

Try it on your store. Restock Ops adds purchase orders with partial receiving, supplier notes, cost history, barcode labels, scanner stocktakes and a reorder report on top of Shopify inventory. From $19/month, 14-day free trial.

Install on Shopify Watch the demo

Sources