Skip to content

moq-mux: replace anyhow with thiserror#1495

Open
kixelated wants to merge 4 commits into
mainfrom
claude/stupefied-chandrasekhar-da73a5
Open

moq-mux: replace anyhow with thiserror#1495
kixelated wants to merge 4 commits into
mainfrom
claude/stupefied-chandrasekhar-da73a5

Conversation

@kixelated
Copy link
Copy Markdown
Collaborator

Summary

  • moq-mux is a library, so per the workspace convention (thiserror for libs, anyhow for binaries) it shouldn't be exporting anyhow types in its public API.
  • Each codec, container, and catalog format gets its own Error enum, flattened into crate::Error via #[from]: codec::{annexb,aac,opus,h264,h265,av1}::Error, container::{fmp4,mkv,hls}::Error, catalog::msf::Error.
  • Pure parsing functions (Config::parse, Sps::parse, Avcc::parse, Avc1/Hvc1::transform, etc.) return their module-local Result. Importer/exporter struct methods return crate::Result because they interleave codec errors with moq_net::Error and the other leaf errors that flow through track operations.

Downstream impact

  • libmoq::Error::{InitFailed,DecodeFailed} now wrap Arc<moq_mux::Error> instead of Arc<anyhow::Error>. Added a BufferNotConsumed variant for the one ad-hoc anyhow!() site that didn't fit either bucket.
  • moq-cli's PublishDecoder keeps anyhow::Result and bridges moq_mux::Result with explicit ?.

Test plan

  • just check (cargo check + clippy -D warnings + fmt --check + doc + shear + sort) passes
  • cargo test -p moq-mux — 141 tests pass
  • cargo check --workspace --all-targets --exclude moq-gst builds (moq-gst is blocked by a local gstreamer install only, not by these changes)

🤖 Generated with Claude Code
(Written by Claude)

moq-mux is a library crate; per the workspace convention (thiserror for
libraries, anyhow for binaries) it shouldn't be exporting anyhow types
in its public API.

Each codec, container, and catalog format module now exports its own
Error enum (codec::{annexb,aac,opus,h264,h265,av1}::Error,
container::{fmp4,mkv,hls}::Error, catalog::msf::Error), flattened into
crate::Error via #[from]. Pure parsing functions (Config::parse,
Sps::parse, Avcc::parse, Avc1/Hvc1::transform, etc.) return their
module-local Result; importer/exporter structs return crate::Result so
they can mix codec errors with moq_net::Error and the other leaf
errors that flow through track operations.

Downstream:
- libmoq::Error::{InitFailed,DecodeFailed} now wrap Arc<moq_mux::Error>
  instead of Arc<anyhow::Error>; added BufferNotConsumed for the one
  ad-hoc anyhow!() site that didn't fit either bucket.
- moq-cli's PublishDecoder bridges moq_mux::Result into anyhow::Result
  with explicit `?` since the binary still uses anyhow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 24, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5c1c13fb-785f-4de8-a268-6cd214753df9

📥 Commits

Reviewing files that changed from the base of the PR and between cd4a77a and 4737fac.

📒 Files selected for processing (1)
  • rs/moq-mux/src/container/fmp4/mod.rs

Walkthrough

This PR removes the anyhow dependency and replaces untyped error handling with typed Error enums and Result aliases across moq-mux and consumers. It adds/expands crate- and module-level Error variants (including BufferNotConsumed and UnknownFormat), updates codec parsers and iterators (AAC, Opus, AV1, H.264, H.265, Annex-B), refactors container importers/exporters (fMP4, HLS, MKV), converts MSF catalog decoding, updates import/stream dispatchers, and adapts libmoq/moq-cli FFI/CLI surfaces to use moq_mux::Error. All mappings that used ensure!/bail!/context are converted to explicit Error variants and ok_or/map_err paths.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'moq-mux: replace anyhow with thiserror' clearly and specifically summarizes the main change in the pull request.
Description check ✅ Passed The description comprehensively explains the motivation (workspace convention), implementation approach (per-module Error enums), API distinctions, downstream impacts, and test results, all directly related to the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/stupefied-chandrasekhar-da73a5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

kixelated and others added 2 commits May 24, 2026 19:02
- Drop unused crate::Error::NotInitialized variant.
- Consolidate fmp4::Error::{NoMoof,MissingMoof} and {NoMoov,MissingMoov}
  duplicates; both pairs described the same condition. Tighten the
  remaining messages to match the Missing* sibling variants.
- Add Result<T> type aliases to container::{fmp4,mkv,hls} and
  catalog::msf so all per-module error enums expose one. fmp4's Wire
  Container impl falls back to std::result::Result because it needs the
  two-arg form for Self::Error.
- Reorder libmoq::Error::ReturnCode so BufferNotConsumed sits next to
  its numeric neighbors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…drasekhar-da73a5

# Conflicts:
#	rs/libmoq/src/error.rs
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rs/moq-mux/src/container/fmp4/mod.rs (1)

192-227: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Return an explicit bounds error instead of silently truncating decoded samples.

On Line 225, decode returns Ok(frames) when sample bounds exceed mdat length. That silently accepts truncated/corrupt fragments. This should fail with Error::SampleRangeOutOfBounds.

Proposed fix
-			if end > mdat_data.len() {
-				return Ok(frames);
-			}
+			if end > mdat_data.len() {
+				return Err(Error::SampleRangeOutOfBounds {
+					start: offset,
+					end,
+					len: mdat_data.len(),
+				});
+			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rs/moq-mux/src/container/fmp4/mod.rs` around lines 192 - 227, The decode
function currently returns Ok(frames) when a sample's end index exceeds
mdat_data length, silently truncating; change this to return
Err(Error::SampleRangeOutOfBounds) instead. In the loop inside decode (for trun
in &traf.trun { for entry in &trun.entries { ... }}), replace the early return
Ok(frames) when end > mdat_data.len() with an Err(...) using
Error::SampleRangeOutOfBounds so malformed/corrupt fragments fail rather than
being silently accepted; ensure the error is propagated from decode's
Result<Vec<Frame>> signature.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@rs/moq-mux/src/container/fmp4/mod.rs`:
- Around line 192-227: The decode function currently returns Ok(frames) when a
sample's end index exceeds mdat_data length, silently truncating; change this to
return Err(Error::SampleRangeOutOfBounds) instead. In the loop inside decode
(for trun in &traf.trun { for entry in &trun.entries { ... }}), replace the
early return Ok(frames) when end > mdat_data.len() with an Err(...) using
Error::SampleRangeOutOfBounds so malformed/corrupt fragments fail rather than
being silently accepted; ensure the error is propagated from decode's
Result<Vec<Frame>> signature.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9a25ca6-6721-4931-9a1e-34b19c872c8f

📥 Commits

Reviewing files that changed from the base of the PR and between 42f6c50 and cd4a77a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (28)
  • rs/libmoq/src/error.rs
  • rs/libmoq/src/publish.rs
  • rs/moq-cli/src/publish.rs
  • rs/moq-mux/Cargo.toml
  • rs/moq-mux/src/catalog/msf/consumer.rs
  • rs/moq-mux/src/catalog/msf/mod.rs
  • rs/moq-mux/src/codec/aac/import.rs
  • rs/moq-mux/src/codec/aac/mod.rs
  • rs/moq-mux/src/codec/annexb.rs
  • rs/moq-mux/src/codec/av1/import.rs
  • rs/moq-mux/src/codec/av1/mod.rs
  • rs/moq-mux/src/codec/h264/import.rs
  • rs/moq-mux/src/codec/h264/mod.rs
  • rs/moq-mux/src/codec/h265/import.rs
  • rs/moq-mux/src/codec/h265/mod.rs
  • rs/moq-mux/src/codec/opus/import.rs
  • rs/moq-mux/src/codec/opus/mod.rs
  • rs/moq-mux/src/container/fmp4/export.rs
  • rs/moq-mux/src/container/fmp4/import.rs
  • rs/moq-mux/src/container/fmp4/mod.rs
  • rs/moq-mux/src/container/hls/import.rs
  • rs/moq-mux/src/container/hls/mod.rs
  • rs/moq-mux/src/container/mkv/export.rs
  • rs/moq-mux/src/container/mkv/import.rs
  • rs/moq-mux/src/container/mkv/mod.rs
  • rs/moq-mux/src/container/source.rs
  • rs/moq-mux/src/error.rs
  • rs/moq-mux/src/import.rs
💤 Files with no reviewable changes (1)
  • rs/moq-mux/Cargo.toml

decode() previously returned Ok(frames) when a sample's end index
exceeded mdat length, silently truncating the frame list. By the time
decode() runs the full CMAF fragment is in hand, so a size mismatch is
a corrupt-publisher signal rather than a streaming-truncation case
worth tolerating. Returning Error::SampleRangeOutOfBounds lets the
caller see the failure instead of receiving a misleading partial decode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kixelated
Copy link
Copy Markdown
Collaborator Author

Addressed the out-of-bounds-samples finding in 4737fac: decode() now returns Error::SampleRangeOutOfBounds instead of silently truncating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant