Here's the verdict up front: when shipping labels go missing, the carrier is almost never at fault. The order died somewhere in your own integration chain, between the WMS and the carrier's label API. Don't start by calling the carrier. Debug in this order: WMS dispatch → API/queue layer → carrier response → status write-back → print station. Wherever the order stops, that's where your problem lives. Get the order wrong and you'll burn three days finding nothing.
Why orders "vanish into thin air"
A label request travels through five links before it lands on a parcel:
- The WMS generates a shipment request.
- The integration layer (or middleware) sends it to the carrier's API.
- The carrier returns label data and a tracking number.
- The WMS writes the tracking number back to the order and moves it to "ready to print."
- The pack station prints the label and the worker slaps it on the box.
Every link can swallow an order: the request never leaves, it rots in an unconsumed queue, your side times out before reading the carrier's response, the write-back fails, the printer is offline. Errors are the easy case — at least you can see them. The killer is the silent failure: your WMS thinks it sent the request, the carrier thinks it never arrived, and the order sits in the gap, claimed by neither. That's why the warehouse screams "lost orders" while IT insists "the logs look fine."
I've seen this three times: two war stories
First one, last November, a 3PL apparel warehouse in eastern China on the UPS label API. Twenty to thirty labels a day went missing, and the carrier swore their backend never got the requests. An afternoon of digging found it: the timeout was 5 seconds, and during peak season the carrier's API answered in 8 to 10. Every timeout made the WMS mark the order "label failed" — while the carrier had already generated the label and tracking number. Two stories, one order: the WMS showed failures waiting for manual reprint, the carrier's billing had already charged for the labels. Worse, the warehouse saw "failed" and hit retry, and the retry produced a second tracking number for the same order. Two candidate labels per parcel — pick the wrong one and it's a lost package plus an angry customer.
Second one, this March, a cross-border e-commerce warehouse in southern China on an international carrier's API. Orders placed between midnight and 2 AM vanished in bulk; daytime was perfectly fine. Nastier root cause: the carrier's API had a nightly maintenance window that returned "service unavailable," and the WMS integration layer had no failure queue at all. Failed requests were simply dropped — no retry, no alert, no record. Two hours of orders left zero trace in the system, the orders sat at "awaiting label," and the warehouse assumed the system was lagging and waited until morning. The logs showed the truth: two full hours of requests never even got sent. The integration layer ate them.
Different symptoms, same root cause: nobody was reconciling the label chain. Money gets reconciled. Inventory gets reconciled. Labels? Nobody's job.
The playbook: a five-link debugging chain
This is my go-live-night checklist. I make clients tick every box before launch.
Step 1: Check the WMS dispatch log. Confirm every shippable order has a dispatch-request record with order number, parcel weight and dimensions, and service product. If the order never generated a request inside the WMS, the problem is internal — a stuck order state machine, a dead dispatch scheduler. Skip the API.
Step 2: Check the integration layer's queue. For async dispatch, look at queue backlog, whether consumers are alive, and what's piling up in the dead-letter queue. For sync calls, look at timeout and retry settings. The timeout must never be shorter than the carrier's SLA response ceiling — and during peak season, double it with margin. The apparel warehouse's 5-second timeout got caught right here.

Step 3: Check the carrier response. Every request needs a paired request-response log: what was sent, at what timestamp, what came back, and the tracking number. Logging the request without the response is the same as logging nothing — the worst system I ever saw stored only the words "call successful," not even the tracking number.
Step 4: Check the status write-back. After the carrier returns a tracking number, the WMS must write it back to the order and advance the status to "ready to print." A failed write-back must go into a retry queue, never be silently skipped. Write-back is the heaviest casualty zone — in many systems the request and the write-back are two independent transactions. The request succeeds, the write-back dies, and the order floats in limbo: the carrier has it, the WMS doesn't.
Step 5: Check the printer. The pack-station printer goes offline, runs out of stock, the driver crashes, the label doesn't come out, and the worker clicks "reprint." Reprint must follow the reprint flow — same existing tracking number, new paper. Never issue a fresh label request, or one order becomes two tracking numbers and month-end reconciliation becomes your personal nightmare.
Step 6: Reconcile the full chain. After daily cutoff, run a four-way reconciliation: WMS dispatch count = integration-layer request count = carrier success count = printed count. Any mismatch is your missing labels, quantified. This reconciliation script must exist on day one of go-live — not after the first incident. Write it late and you can't even answer "how many did we lose."
Step 7: Idempotency keys. Every label request carries a globally unique idempotency key. Use order number plus parcel sequence — never bare order number, because multi-parcel orders will collide. Both the carrier side and your own integration layer must deduplicate on the key. This is the only defense against "retry prints a duplicate label." There is no second one.
| Link | Typical symptom | Debugging action |
|---|---|---|
| WMS dispatch | Orders stuck at "awaiting label," no request record | Check order state machine, dispatch scheduler |
| API queue | Growing latency, dead-letter queue piling up | Check consumer health, queue-depth alerts |
| Carrier response | Frequent timeouts, sporadic failures | Verify timeout settings, carrier status page, paired logs |
| Status write-back | Tracking number exists but order status unchanged | Check write-back transaction, retry queue |
| Print station | Workers report "nothing prints" | Check printer status, use reprint flow, never re-request |
Common failure points (self-check before go-live)
- Timeout set too short. It always explodes during peak season. I've seen this three times, and every time the story starts with "it worked fine until the big sale."
- Failures dropped instead of queued. A midnight maintenance window or a random carrier 500 becomes "order not found."
- Retries without idempotency keys. Retrying feels good; month-end reconciliation is the hangover — the carrier charges for every duplicate label.
- Reconciling money and inventory but not labels. Finance ties out, inventory ties out, and nobody notices a few dozen missing labels until customers report parcels that never arrived.
- Treating "call succeeded" as "label created." A 200 from the carrier API doesn't mean a label was generated. Read the business status code inside the response body — carriers routinely wrap a business failure in an HTTP 200.
The counterintuitive part
The most dangerous failure mode isn't an error — it's fake success. An error triggers an alert and somebody looks. But "request sent, WMS shows success, carrier never received it" can sit quietly for weeks, then detonate on the morning of your biggest sale. One rule defends against it: the carrier's returned tracking number is the only source of truth. Any order without one is treated as never shipped. Align the warehouse and customer service on this before go-live, or all three sides will argue about it after the incident — with IT holding the blame.
One trade-off deserves honesty: synchronous calls versus an async queue. Sync is simple — the worker clicks print and knows the result — but one slow carrier response blocks the whole pack line. Async gives throughput and absorbs spikes, but the chain gets longer and debugging gets twice as hard. My rule: under 5,000 orders a day, go synchronous with short timeouts and a manual-review queue for failures. Above that, go async — but only after the full-chain reconciliation and alerting above are in place. Async isn't a silver bullet; it converts "error in your face" into "reconciliation after the fact." Weak reconciliation makes async losses harder to find than sync ones.
Label APIs look peaceful right up until 3 AM on sale day. Print this checklist and tape it next to the pack station. It beats any dashboard.
By Lin Xiao, WMS Implementation Consultant









