{"record":{"id":"8714ef626554eb21","repo":"tonhowtf/omniget","slug":"downloaded-file-from-is-too-small-b-likely-an-error-page","errorCode":null,"errorMessage":"Downloaded file from {} is too small ({}B) — likely an error page","messagePattern":"Downloaded file from (.+?) is too small \\((.+?)B\\) — likely an error page","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/dependencies.rs","lineNumber":435,"sourceCode":"            return Err(anyhow!(\n                \"Failed to download FFmpeg from {}: HTTP {}\",\n                url,\n                response.status()\n            ));\n        }\n\n        let temp_path = bin_dir.join(\".ffmpeg_download.tmp\");\n        let bytes = response.bytes().await?;\n        let data = bytes.to_vec();\n        let temp_clone = temp_path.clone();\n        tokio::task::spawn_blocking(move || std::fs::write(&temp_clone, &data))\n            .await\n            .map_err(|e| anyhow!(\"spawn_blocking failed: {}\", e))??;\n\n        let file_size = std::fs::metadata(&temp_path)?.len();\n        if file_size < 1_000_000 {\n            let _ = std::fs::remove_file(&temp_path);\n            return Err(anyhow!(\n                \"Downloaded file from {} is too small ({}B) — likely an error page\",\n                url,\n                file_size\n            ));\n        }\n\n        match archive_type {\n            ArchiveType::Zip => {\n                extract_zip_ffmpeg(&temp_path, &bin_dir, &ffmpeg_name, &ffprobe_name).await?\n            }\n            ArchiveType::TarXz => {\n                extract_tar_xz_ffmpeg(&temp_path, &bin_dir, &ffmpeg_name, &ffprobe_name).await?\n            }\n        }\n\n        let _ = std::fs::remove_file(&temp_path);\n    }\n","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/dependencies.rs#L417-L453","documentation":"After writing the downloaded archive to a temp file, download_ffmpeg() checks its size and rejects anything under 1,000,000 bytes, assuming a mirror served an HTML error page or truncated response instead of the real FFmpeg archive. The temp file is deleted and the URL plus actual size are reported.","triggerScenarios":"The mirror returned an HTML error page (login/captcha/soft-404), the response was truncated by a proxy, or a redirect landed on a small landing page instead of the archive.","commonSituations":"Mirror soft-404 after upstream path change; captive portal or proxy interception; CDN serving a tiny error body with 200 OK; disk-quota truncation in rare setups.","solutions":["Inspect the response from the URL manually (curl -L) — it is likely HTML, not an archive","Switch to a working mirror / update the URL list in download_ffmpeg","Retry later if the mirror or network is degraded","Bypass any proxy that rewrites responses","If legitimate archives could be under 1MB (custom builds), adjust the size threshold"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if let Ok(meta) = std::fs::metadata(tmp) {\n    if meta.len() < 1_000_000 {\n        eprintln!(\"downloaded payload too small — mirror returned an error page\");\n    }\n}","typeGuard":null,"tryCatchPattern":"match download_ffmpeg().await {\n    Ok(p) => ...,\n    Err(e) if e.to_string().contains(\"too small\") => try_next_mirror(),\n    Err(e) => ...,\n}","preventionTips":["Validate content-type/content-length headers before accepting the body","Maintain multiple mirrors and rotate on suspicious payloads","Prefer checksum verification over pure size thresholds","Alert when a previously working mirror starts returning small bodies"],"tags":["network","download","ffmpeg","validation"],"backgroundTag":"unexpected-response-shape","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}