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
- 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.
- 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.
- If your use case genuinely needs larger manifests, raise MAX_MANIFEST_BYTES (extension_manifest.rs:38) after assessing disk/memory impact.
- 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
- Only pass URLs that actually return m3u8 content to store_manifest.
- Log the response size before storing so pathological sources are visible early.
- Cap segment counts fetched from live/DVR streams to keep playlists small.
- Re-check MAX_MANIFEST_BYTES if your sources legitimately grow beyond 4 MiB.
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
- cole a URL de um .m3u8 ou .mpd
- {:.0} MB não cabem {:.0}s de vídeo — aumente o alvo ou encur
- No valid cookies found in file (expected Netscape format)
- Download cancelled by user
- Failed to parse m3u8: neither master nor media playlist
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)