# Telemetry gap

URL: /rules/telemetry-gap

Flags a stretch where the ground receiver heard no HEARTBEAT from a vehicle for longer than the threshold. It observes a receive gap, not a radio failure.



<RuleHeader id="telemetry_gap" />

## What it reads [#what-it-reads]

The rule reads the ground receive log: one record per MAVLink message that reached the receiver at range control, with the vehicle's system ID and the receiver's own timestamp. It looks only at `HEARTBEAT` messages (`msgid` 0) from the vehicle's system ID.

MAVLink systems send `HEARTBEAT` at 1 Hz on typical radio links, so the expected interval between two receipts is 1 s. The rule measures the time between consecutive heartbeats from the same system ID.

## When it fires [#when-it-fires]

A finding is produced when two consecutive heartbeats from the same vehicle are more than **3 s** apart. The event is placed where the next heartbeat was due, one expected interval after the last one received, and it records:

| Value                  | Example from INC-0142                |
| ---------------------- | ------------------------------------ |
| Last received          | 14:32:03.912                         |
| Next received          | 14:32:10.874                         |
| Expected interval      | 1 s (HEARTBEAT at 1 Hz)              |
| Gap threshold          | 3 s                                  |
| Link latency, this run | median 96 ms, 95th percentile 412 ms |

The finding's title states the silence, for example **Heartbeat due and not received. Nothing for 6.96 s**.

## Wording and evidence level [#wording-and-evidence-level]

Every finding reads **Observed: telemetry receive gap, not necessarily radio failure**. The receive log directly shows that nothing arrived, so the level is observed. Why nothing arrived is a separate question, and the wording keeps it open.

## What the finding does not mean [#what-the-finding-does-not-mean]

* **The radio did not necessarily fail.** In INC-0142 the gap began less than a second after the MAVLink router stopped on the companion computer. In INC-0143 the radio dropped off the companion's USB bus. Both look the same in the receive log.
* **The vehicle did not necessarily stop sending.** Terrain can mask the link while the vehicle transmits normally, as in INC-0137, where the gap matches the stretch in which the berm rises above the line of sight from the range control mast.
* **PX4 did not necessarily see a link loss.** The flight controller has its own view in `telemetry_status`. It marks `heartbeat_type_gcs` false once 2.5 s pass without a ground heartbeat (`HEARTBEAT_TIMEOUT_US`), and it enters the data link failsafe only after `COM_DL_LOSS_T`, 10 s by default. A 6.96 s receive gap on the ground can pass with no failsafe at all.
* **The gap does not start at the last receipt.** Receipts trail transmissions by the link latency. The last heartbeat before the INC-0142 gap left the vehicle between 14:32:03.485 and its arrival at 14:32:03.912.

## Threshold and overrides [#threshold-and-overrides]

The 3 s threshold sits between the 1 s heartbeat period and the 10 s default of `COM_DL_LOSS_T`, so the finding appears before a default data link failsafe would. Change it under **Rules** with **Edit**. The rule saves as the next version, and findings already produced keep the version and threshold that made them. See [Thresholds, scopes and overrides](/rules/configure).

## Example finding [#example-finding]

In INC-0142, UAS-04 flew the return leg of Route Iron. The receiver at range control heard nothing from system ID 4 for 6.96 s. On the companion journal, `mavlink-router.service` stopped at 14:32:04.152, 34 ms after the kernel killed `perception_node`, and the next heartbeat was due at 14:32:04.912. The report files the gap as correlated with the router stopping: 0.76 s apart against a bound of ±0.43 s including link latency.

## Related [#related]

* [failsafe\_entered](/rules/failsafe-entered) reports what PX4 did about a lost link.
* [process\_exit](/rules/process-exit) and [device\_disconnect](/rules/device-disconnect) cover the two causes the examples show.
* [Receiver JSONL records](/reference/receiver-jsonl) describes the records this rule reads.
