livekit/livekit · warning
cannot start on rtx packet
Error message
cannot start on rtx packet
What it means
The stream buffer refuses to begin RTP stats tracking when the first packet processed is a retransmission (RTX) while rtpStats is not yet active. Starting a stream on an RTX packet would corrupt sequence-number accounting because the original sequence number belongs to an earlier stream position.
Source
Thrown at pkg/sfu/buffer/buffer_base.go:779
if flowState.UnhandledReason == rtpstats.RTPFlowUnhandledReasonNone && !flowState.IsOutOfOrder {
if err := b.snRangeMap.ExcludeRange(flowState.ExtSequenceNumber, flowState.ExtSequenceNumber+1); err != nil {
b.logger.Errorw(
"could not exclude range", err,
"sequenceNumber", sn,
"extSequenceNumber", flowState.ExtSequenceNumber,
"rtpStats", b.rtpStats,
"rtpStatsLite", b.rtpStatsLite,
"snRangeMap", b.snRangeMap,
"skipped", skippedSeqs,
)
}
}
}
}
// do not start on an RTX packet
if isRTX && !b.rtpStats.IsActive() {
return 0, errors.New("cannot start on rtx packet")
}
flowState := b.rtpStats.Update(
arrivalTime,
rtpPacket.Header.SequenceNumber,
rtpPacket.Header.Timestamp,
rtpPacket.Header.Marker,
rtpPacket.Header.MarshalSize(),
len(rtpPacket.Payload),
int(rtpPacket.Header.PaddingSize),
)
switch flowState.UnhandledReason {
case rtpstats.RTPFlowUnhandledReasonNone:
case rtpstats.RTPFlowUnhandledReasonRestart:
if !b.enableStreamRestartDetection {
return 0, fmt.Errorf("unhandled reason: %s", flowState.UnhandledReason.String())
}
View on GitHub (pinned to ee45c3f0b1)
Solutions
- Usually transient: the next non-RTX packet initializes the stream; retry/let the track re-buffer.
- Check publisher uplink quality — persistent early RTX indicates pre-join loss.
- Upgrade LiveKit; RTX handling/repair logic has been improved across releases.
- If reproducible, capture publisher-side traces to confirm RTX-before-original ordering.
Defensive patterns
Strategy: retry
Try / catch
// SFU-internal: treat as transient stream-start failure
if err := buffer.Read(...); errors.Is(err, errCannotStartOnRTX) {
// wait for next non-RTX packet; do not tear down the track
continue
} Prevention
- Maintain healthy publisher uplink to reduce pre-join retransmissions.
- Keep LiveKit updated for RTX-start handling improvements.
- Monitor error frequency per track; persistent occurrences signal upstream loss.
- Avoid restarting tracks mid-loss-burst when possible.
When it happens
Trigger: A subscriber/track begins being forwarded and the first packet arriving at the buffer is an RTX retransmission (matched via the RTX SN cache or SN offset heuristic) before any original packet initializes stats.
Common situations: Joining a room mid-stream with packet loss where the very first received packet is a retransmission; publisher-side network producing RTX before original packets reach the SFU; track restart/reconnect scenarios.
Related errors
AI-assisted analysis of livekit/livekit@ee45c3f0b1 (2026-09-02).
Data as JSON: /api/errors/de0d3fe9341d2903.
Report an issue: GitHub.