tonhowtf/omniget · error · anyhow::Error

Extension playlist is {} bytes, over the {} byte limit

Error message

Extension playlist is {} bytes, over the {} byte limit

What it means

store_manifest_in persists a fetched HLS extension playlist manifest to disk as text, but refuses to store anything larger than MAX_MANIFEST_BYTES (4 MiB). Oversized manifests are treated as suspicious/unbounded responses, so the write is rejected up front with the actual size and the limit in the message. This protects the manifest cache from pathological or attacker-influenced playlists.

Solutions

  1. Verify the URL actually points to an m3u8 playlist; a normal playlist is far below 4 MiB, so a size breach usually means the wrong URL or a non-playlist response.
  2. If the stream legitimately has a huge media playlist, fetch a rolling/sliding window (e.g. use the playlist's segment window or start from a recent segment) instead of storing the whole manifest.
  3. If your use case genuinely needs larger manifests, raise MAX_MANIFEST_BYTES (extension_manifest.rs:38) after assessing disk/memory impact.
  4. Pre-validate the manifest size client-side before calling store_manifest to give a better error to end users.

Example fix

// before
store_manifest(url, &giant_playlist_text)?; // bails if > 4 MiB
// after
if giant_playlist_text.len() > MAX_MANIFEST_BYTES {
    // trim to a recent window of segments before storing
    giant_playlist_text = take_recent_segment_window(&giant_playlist_text, 500);
}
store_manifest(url, &giant_playlist_text)?;
Defensive patterns

Strategy: validation

Validate before calling

const MAX_MANIFEST_BYTES: usize = 4 * 1024 * 1024;
if manifest_text.len() > MAX_MANIFEST_BYTES {
    eprintln!("manifest too large: {} bytes", manifest_text.len());
} else {
    store_manifest(url, &manifest_text)?;
}

Try / catch

// Rust: match on the store result and degrade gracefully
match store_manifest(url, &text) {
    Ok(()) => {},
    Err(e) if e.to_string().contains("byte limit") => {
        // fetch a trimmed/sliding-window manifest instead
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling store_manifest (or store_manifest_in, directly in tests) with playlist text whose byte length exceeds 4 * 1024 * 1024: a huge master playlist with thousands of variants, a media playlist with an enormous number of segments, or a misconfigured/non-HLS endpoint returning a large body that was mistakenly treated as a playlist.

Common situations: Pointing the downloader at a URL that returns a giant HTML page or binary blob instead of an m3u8; streams with extremely long DVR windows generating massive media playlists; hostile endpoints serving multi-gigabyte 'playlists' to exhaust disk.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/7e792d345ab2b6fa. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/extension_manifest.rs:86

/// Playlist text captured for `url`, when one exists and is still fresh.
/// Never panics: every failure path collapses into `None`.
pub fn load_manifest_for_url(url: &str) -> Option<String> {
    load_manifest_in(&manifest_dir(), url, SystemTime::now())
}

/// A file stamped in the future (clock skew, restored backup) counts as
/// fresh rather than as an error.
fn is_expired(modified: SystemTime, now: SystemTime) -> bool {
    match now.duration_since(modified) {
        Ok(age) => age.as_secs() > MANIFEST_TTL_SECS,
        Err(_) => false,
    }
}

fn store_manifest_in(dir: &Path, url: &str, text: &str, now: SystemTime) -> anyhow::Result<()> {
    if text.len() > MAX_MANIFEST_BYTES {
        anyhow::bail!(
            "Extension playlist is {} bytes, over the {} byte limit",
            text.len(),
            MAX_MANIFEST_BYTES
        );
    }

    fs::create_dir_all(dir)?;
    prune_expired_in(dir, now);

    let path = dir.join(manifest_file_name(url));
    fs::write(&path, text)?;

    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        fs::set_permissions(&path, fs::Permissions::from_mode(0o600))?;
    }

View on GitHub (pinned to 8600b91f42)