You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
export ts --stitch --follow: a hard-killed importer can end the export on a missed decode deadline instead of a switch #6802
Two importers publish one broadcast, the second started 8 s after the first, so the relay serves
the newer one. Two export ts --stitch --follow 10s --delay 2s subscribers read it. When the
serving importer is SIGKILLed, an export usually switches to the remaining importer as a marked
programme switch. In 3 of 13 runs, one of the two exports instead fails, and its follower gives up:
WARN moq_mux::container::consumer: current group evicted; skipping to next buffered group track="0.avc3" group=18 error=Moq(Stream(Unroutable))
WARN moq_mux::container::ts::follower: export failed, so not following path=t56.kill.8860 err=MPEG-TS output missed a decode deadline on PID 111 at 9945950 b/s, sent as far ahead as its decoder buffer holds; raise the multiplex rate
Error: MPEG-TS output missed a decode deadline on PID 111 at 9945950 b/s, sent as far ahead as its decoder buffer holds; raise the multiplex rate
The first importer is live throughout, and the other export of the same run switches to it. The
failure comes in the same millisecond as the killed importer's tracks going unroutable.
QUIC idle timeout (keep-alive a third)
Runs
An export failed
1 s
3
0
2 s
3
0
4 s
3
1
6 s
4
2
None failed on SIGTERM (6 runs), at any of the follower's 54 "broadcast replaced" switches (the
second importer's start, the killed one's restart), with the second importer on a separate encode
(3 hard kills), or when the serving importer's uplink was dropped for 1–2 s at a 1 s idle timeout
(6 runs, Linux).
Related: #5052 was the same error after a re-request onto a live route, fixed by #5109 (video held
through a silence drops as late). This is the follower's path after a hard kill.
Reproduction
main at 66af72315 (moq 0.14.2, moq-relay 0.17.2), macOS, loopback, one relay, moq-lite-06
negotiated. The source is a 1080i H.264 contribution file at 9.95 Mb/s CBR, played in real time
(tsp -P regulate --pcr-synchronous) into a file that each moq import ts follows from its own
start. --mux-rate is left at its default, the catalog's muxRate, so the output has the source's
rate and no headroom; whether a higher --mux-rate avoids the failure was not tested. Nothing in
the follower, export or scheduler has changed on main since.
Expected
The source going away mid-group is the same discontinuity the follower already handles when a
broadcast is replaced: a marked switch to the importer still announced, with the late access units
dropped, not a fatal scheduling error that also stops the follow.
#6656 - feat(mux)!: TS export follows by cause, and --linger is --follow [merged]
📝 Issue Planner
Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.
Create Plan
🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your .coderabbit.yaml:
issue_enrichment:
auto_enrich:
enabled: false
💬 Have feedback or questions? Drop into our discord!
Diagnosis (to be confirmed by a failing test first): a SIGKILLed importer is noticed only after the QUIC idle timeout. When its tracks then go Unroutable, the consumer's cut flushes the video frames still held for their DTS, stamped with the last frame's arrival from before the silence. They pass the jitter buffer as on time, land behind the schedule, and missed() ends the export. #5109 fixed the same stale stamp when a later frame settles the held frames; a cut settles them with no frame. This matches your table: idle timeouts at or under the 2 s delay never failed.
Decisions
A cut carries the instant the loss was observed, and the frames it releases are judged as arriving then. Frames held through a silence longer than the delay drop as late, and the follower switches to the remaining instance.
Every flush path of held frames (cut, restart, skip, group end, end of track) is audited for the same stale arrival.
A genuine multiplex-rate miss stays fatal.
Covered by mock-time unit tests in export_timing_test.rs.
No backport: release has no follower or --stitch.
The quest's PR will close this issue. To donate tokens, run /quest-start quest/m1/ts-reliability/cut-arrival.
Activity
coderabbitai commentedon Oct 25, 2026
🔗 Related PRs
#6656 - feat(mux)!: TS export follows by cause, and --linger is --follow [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
kixelated commentedon Oct 26, 2026
Planned as
quest/m1/ts-reliability/cut-arrival.mdin #6844 (in the merge queue).Diagnosis (to be confirmed by a failing test first): a SIGKILLed importer is noticed only after the QUIC idle timeout. When its tracks then go
Unroutable, the consumer's cut flushes the video frames still held for their DTS, stamped with the last frame's arrival from before the silence. They pass the jitter buffer as on time, land behind the schedule, andmissed()ends the export. #5109 fixed the same stale stamp when a later frame settles the held frames; a cut settles them with no frame. This matches your table: idle timeouts at or under the 2 s delay never failed.Decisions
export_timing_test.rs.releasehas no follower or--stitch.The quest's PR will close this issue. To donate tokens, run
/quest-start quest/m1/ts-reliability/cut-arrival.(Written by Claude Opus 5.5)