When delivery fails
Something is not arriving. This is how to find out where it stopped.
Start with Analytics
Analytics counts what the pipeline did over a window — Received, Delivered, Dead-lettered, Delivery attempts (and how many were retries) and Filtered out (dropped by a rule, or a duplicate) — and lets you narrow every number by project, tenant, technology, provider, message type, source, sink, profile or device. Which one is wrong tells you which half of the system to look at; the Breakdown panel tells you which project, sink or message type it is, and every row opens the matching dead letters.
| Reading | Means |
|---|---|
| Received is 0 | Nothing is arriving. The problem is upstream — the source, not the Center. |
| Received > 0, Delivered 0, Failed 0 | Messages arrive and stop inside. A rule is dropping them, or there is no route. |
| Dead-lettered > 0 | Delivery is being attempted and rejected. The sink or its configuration. Failures by sink names it. |
| Attempts far above Delivered | Deliveries succeed, but only after retries. The sink is slow or flaky. |
| Filtered out > 0 | Rules are dropping messages, or the source is re-sending duplicates. |
| Delivered > 0 but nothing downstream | The sink returns success and discards the body. Look at the receiver. |
That last row catches people out. A sink answering 200 OK while ignoring the
payload looks perfectly healthy from the Center.
Nothing received
Work outwards from the Center:
- Is the callback pointed at the right URL? Check the network's configuration against Flow → Endpoint & schema.
- Was the ingest key rotated? Rotation invalidates the old key immediately — any sender still using it fails from that moment.
- Does the shared secret match on both sides?
- Are required headers being sent? A missing required header is rejected before anything else runs.
- Is the device transmitting at all? Check the network's own console.
Received but not delivered
The message got in and stopped. Two usual causes:
A rule dropped it. Open Flow → Rules and read them top-down. The first match wins, and a rule with Stop can prevent later rules from ever running. Deactivate a suspect rule rather than deleting it while you test.
There is no route. If the project has any routes at all, delivery is explicit — a source with no wire to a sink delivers nowhere. Check Flow → Routing. Removing what looked like a redundant route can silently orphan a source.
Failed deliveries and dead letters
A failed delivery retries with growing backoff. When it has used up the attempts its project's delivery policy allows — eight by default, with a 5 s → 10 s → 20 s … curve — it is dead-lettered and appears in Dead letters. The policy lives on the project page (Delivery & dead letters): attempts, the first delay, the multiplier, the longest wait, the per-attempt timeout and how long dead letters are kept; the card shows the resulting retry schedule as you edit it.
Dead letters are parked, not lost. The list filters the same way Analytics does — tenant, project, technology, provider, message type, source, sink, profile, device — plus a search over the error text, device identifier or an id, and every row shows the source → sink pair, the radio, the message type, the HTTP status and when it was dead-lettered.
Open a letter to see what happened. The drawer's timeline lists every attempt — its number, HTTP status, error class, duration and payload size — across every replay, followed by the context (project, source, sink, device, profile, message type, all links), the policy that governed it, and the body that would be resent.
Fix, then replay
- Fix the cause — correct the sink URL, renew the token, fix the output structure, whatever the failure was.
- Open Dead letters and hit Replay.
Replay starts a new run of the same delivery: its attempts start again from one under today's policy, and every earlier attempt stays in the timeline with the replay itself and who asked for it. Replay all matching re-queues every dead letter the current filters match, oldest first.
Common causes
| Failure | Usually |
|---|---|
| Connection refused / timeout | Sink is down, or unreachable from the Center |
| 401 / 403 | Expired token, rotated credential, IP restriction |
| 404 | Endpoint URL changed |
| 400 / 422 | The sink rejects the shape — check the output structure |
| 5xx | The receiver's own problem; replay once it is healthy |
Use the sink's Test button after any fix. It exercises the connection immediately instead of making you wait for the next uplink.
Delivered, but the data looks wrong
Delivery succeeded, so this is a shaping or decoding question. The pipeline order tells you where to look:
- Payload is still hex — no decoder, wrong profile, or the decoder threw.
Check
payload.decodeError. - Fields missing — the output structure omits them, or they were absent from
that message. Missing fields are omitted rather than sent as
null. - Shape changes between messages — a decoded-only structure falling back because some callbacks carry no payload.
- Duplicates — expected. The Center delivers
at least once; de-duplicate on
idempotencyKey.
A quick checklist
- Analytics — which counter is wrong, and for which project, sink or message type?
- Dead letters — anything parked? Open one: which attempt failed how?
- Flow → Rules — is something dropping it?
- Flow → Routing — is the pair actually wired?
- Sink → Test — does the connection even work?
- The receiver's own logs — is it accepting and discarding?