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 --linger exits on internal error when its catalog request lands on a publisher that just died #5347
A concrete case for quest/m1/dropped-sources.md,
with one consequence the quest doesn't list: ts::Follower exempts Dropped from failing loud, but a
drop forwarded by a relay arrives as internal error, so the exemption can only match locally.
On main at 90500867d, moq export ts --delay 1s --linger 60s --stitch on the default moq-lite-06 exited 1 with moq: internal error in 1 of 4 crash-replace runs; the other three
resumed at every replacement. Rig: one relay on loopback, the export started first, then three moq import ts sessions of one broadcast, 15 s each, the first two SIGKILLed 5 s before their end and
each replaced 3 s later. Default idle timeout.
Session 0 is killed at 10:22:34.0; session 1 connects at 10:22:37.3 and is killed at 10:22:47.20.
At 10:22:46.95 the relay times session 0 out and ends the export's subscriptions; the export logs broadcast ended, waiting for it to return at 10:22:47.26 and sends a catalog track info request.
The relay routes it to session 1, dead for 60 ms but not yet timed out. At 10:22:57.26 it times
session 1 out and logs track info error … track=catalog.json err=dropped; the export logs track info failed … err=internal error and exits. Session 2, up since 10:22:50.5, would have
served the return.
Error::Dropped has no arm in From<&Error> for StreamError, so it goes out as Internal, and State::Following in rs/moq-mux/src/container/ts/follower.rs treats any resolve error but Unroutable | Dropped as a refusal from a live instance. If the quest ends this path with Unroutable, as it plans for requests a front aborts, the follower resumes here unchanged; the
quest's regression could cover a request in flight when the upstream session times out. On moq-lite-07 the replacement's epoch ends the old broadcast first, so we did not see it there.
Confirmed, and we've folded this into quest/m1/dropped-sources.md (planned in #5358) with two changes from what the issue anticipates.
Root cause: a Dropped that reaches the wire is a bug, since some path never ended with a proper error. On epochless lite-06, the front ended with Dropped when its only route timed out. A route that fails under a request or track (the upstream session dies, and nothing replaces it) now ends downstream with Unroutable. Every error variant gets a real wire mapping instead of the Internal catch-all.
Follower: matching on Unroutable alone would not have fixed this, because a remote Unroutable arrives as Error::Stream(StreamError::Unroutable). Rather than match errors at all, ts::Follower becomes announcement-driven while it lingers. A resolve error sends it back to waiting for the next announcement. A new announcement cancels an in-flight resolve, so it no longer sits out a dead session's idle timeout. --linger expiry is the only exit, and it fails with the last resolve error if there was one.
Anyone who wants to donate tokens can run /quest-start quest/m1/dropped-sources.
Activity
kixelated commentedon Oct 12, 2026
Confirmed, and we've folded this into
quest/m1/dropped-sources.md(planned in #5358) with two changes from what the issue anticipates.Droppedthat reaches the wire is a bug, since some path never ended with a proper error. On epochless lite-06, the front ended withDroppedwhen its only route timed out. A route that fails under a request or track (the upstream session dies, and nothing replaces it) now ends downstream withUnroutable. Every error variant gets a real wire mapping instead of theInternalcatch-all.Unroutablealone would not have fixed this, because a remote Unroutable arrives asError::Stream(StreamError::Unroutable). Rather than match errors at all,ts::Followerbecomes announcement-driven while it lingers. A resolve error sends it back to waiting for the next announcement. A new announcement cancels an in-flight resolve, so it no longer sits out a dead session's idle timeout.--lingerexpiry is the only exit, and it fails with the last resolve error if there was one.Anyone who wants to donate tokens can run
/quest-start quest/m1/dropped-sources.(Written by Claude Opus 5.5)
quest(m1): import moq-dev#5257-moq-dev#5259, moq-dev#5347, moq-dev#5348…
fix(net): consumers see the source's real error, never Dropped
fix(net): consumers see the source's real error, never Dropped
fix(net): consumers see the source's real error, never Dropped