diff --git a/rs/moq-net/src/lite/subscriber.rs b/rs/moq-net/src/lite/subscriber.rs index 46b90b0d5c..c0ab106215 100644 --- a/rs/moq-net/src/lite/subscriber.rs +++ b/rs/moq-net/src/lite/subscriber.rs @@ -766,7 +766,11 @@ impl GroupRecv { } }; - let GroupRecvState::Serve { group, .. } = std::mem::replace(&mut self.state, GroupRecvState::Done) + // Held until the group settles below, so a frame the track or group cut + // short drops into an already-aborted group instead of reporting a loss. + let GroupRecvState::Serve { + group, ingest: _ingest, .. + } = std::mem::replace(&mut self.state, GroupRecvState::Done) else { unreachable!() }; diff --git a/rs/moq-net/src/model/frame.rs b/rs/moq-net/src/model/frame.rs index 0b344f2f97..d2eab832f2 100644 --- a/rs/moq-net/src/model/frame.rs +++ b/rs/moq-net/src/model/frame.rs @@ -359,11 +359,16 @@ impl> Drop for Raw { if !self.done { // An unfinished frame leaves the group stream broken; fail the group so // consumers surface an error instead of hanging on the partial forever. - tracing::warn!( - group = self.group.borrow_mut().info().sequence, - "frame::Producer dropped before writing all bytes" - ); - self.group.borrow_mut().frame_abort(Error::Dropped); + // A group already aborted (superseded, evicted, cancelled) carries its own + // reason, so cutting its in-flight frame short is expected. + let group = self.group.borrow_mut(); + if !group.is_aborted() { + tracing::warn!( + group = group.info().sequence, + "frame::Producer dropped before writing all bytes" + ); + } + group.frame_abort(Error::Dropped); } } } diff --git a/rs/moq-net/src/model/resume.rs b/rs/moq-net/src/model/resume.rs index e2227a17f1..ee081f1474 100644 --- a/rs/moq-net/src/model/resume.rs +++ b/rs/moq-net/src/model/resume.rs @@ -1214,12 +1214,16 @@ impl Group { Some((_, err)) => { // The only place a spliced group's loss becomes visible, so say which // frames went missing rather than leaving a stuck group to explain itself. - tracing::warn!( - group = self.sequence, - frame = self.index, - %err, - "no route can serve the rest of this group" - ); + // An old group was skipped on purpose (something newer superseded it), so + // it is not a loss worth reporting. + if !matches!(crate::StreamError::from(err), crate::StreamError::Old) { + tracing::warn!( + group = self.sequence, + frame = self.index, + %err, + "no route can serve the rest of this group" + ); + } Err(err.clone()) } None => Ok(false),