{"record":{"id":"d33a3b1fc82f5391","repo":"tonhowtf/omniget","slug":"failed-to-read-tar-entries","errorCode":null,"errorMessage":"Failed to read tar entries: {}","messagePattern":"Failed to read tar entries: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/dependencies.rs","lineNumber":634,"sourceCode":"    bin_dir: &std::path::Path,\n    ffmpeg_name: &str,\n    ffprobe_name: &str,\n) -> anyhow::Result<()> {\n    let archive_path = archive_path.to_path_buf();\n    let bin_dir = bin_dir.to_path_buf();\n    let ffmpeg_name = ffmpeg_name.to_string();\n    let ffprobe_name = ffprobe_name.to_string();\n\n    tokio::task::spawn_blocking(move || {\n        let file = std::fs::File::open(&archive_path)\n            .map_err(|e| anyhow!(\"Failed to open archive: {}\", e))?;\n        let decompressor = xz2::read::XzDecoder::new(file);\n        let mut archive = tar::Archive::new(decompressor);\n        let targets = [ffmpeg_name.as_str(), ffprobe_name.as_str()];\n\n        for entry_result in archive\n            .entries()\n            .map_err(|e| anyhow!(\"Failed to read tar entries: {}\", e))?\n        {\n            let mut entry = entry_result.map_err(|e| anyhow!(\"Failed to read tar entry: {}\", e))?;\n            let path = entry\n                .path()\n                .map_err(|e| anyhow!(\"Failed to read entry path: {}\", e))?;\n            let file_name = path.file_name().and_then(|n| n.to_str()).unwrap_or(\"\");\n            for target in &targets {\n                if file_name == *target {\n                    let dest = bin_dir.join(format!(\"{}.new\", target));\n                    let mut out = std::fs::File::create(&dest)?;\n                    std::io::copy(&mut entry, &mut out)?;\n                    break;\n                }\n            }\n        }\n        Ok::<(), anyhow::Error>(())\n    })\n    .await","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/dependencies.rs#L616-L652","documentation":"After opening the .tar.xz and wrapping it in an xz2 XzDecoder and tar::Archive, extract_tar_xz_ffmpeg calls archive.entries() to iterate members. Failure here means the tar iterator could not be created/started - typically the underlying stream is not a valid tar, or the xz stream is corrupt/truncated.","triggerScenarios":"The downloaded file is not actually xz-compressed tar (e.g. gzip tar or plain HTML error page), the xz stream is truncated mid-download, or the tar header block is invalid.","commonSituations":"Upstream changed the artifact from .tar.xz to .tar.gz but the extractor was not updated; proxy returned an error page saved with a .tar.xz name; incomplete download on flaky network.","solutions":["Delete and re-download the archive; verify integrity (size/checksum) before extraction","Verify the file magic bytes: FD 37 7A 58 5A 00 for xz, and gzip's 1F 8B if the upstream switched formats","Use the matching decoder (GzDecoder vs XzDecoder) for the actual format","Check that the download response status was success and Content-Length matched"],"exampleFix":"// before\nlet decompressor = xz2::read::XzDecoder::new(file);\n// after\nlet mut magic = [0u8; 6];\nlet mut peek = std::fs::File::open(&archive_path)?;\nuse std::io::Read;\npeek.read_exact(&mut magic)?;\nif &magic != b\"\\xfd7zXZ\\x00\" {\n    return Err(anyhow!(\"Downloaded artifact is not an xz archive; re-download or switch decoder\"));\n}\nlet decompressor = xz2::read::XzDecoder::new(peek);","handlingStrategy":"validation","validationCode":"let mut f = std::fs::File::open(&archive_path)?;\nlet mut magic = [0u8; 6];\nstd::io::Read::read_exact(&mut f, &mut magic)?;\nif &magic != b\"\\xfd7zXZ\\x00\" {\n    return Err(anyhow!(\"artifact is not xz; check upstream format\"));\n}","typeGuard":"fn is_xz_file(p: &std::path::Path) -> bool {\n    use std::io::Read;\n    std::fs::File::open(p).map(|mut f| {\n        let mut m = [0u8; 6];\n        f.read_exact(&mut m).is_ok() && &m == b\"\\xfd7zXZ\\x00\"\n    }).unwrap_or(false)\n}","tryCatchPattern":"match extract_tar_xz_ffmpeg(&path, &bin_dir, &ff, &fprobe).await {\n    Err(e) if e.to_string().contains(\"Failed to read tar entries\") => {\n        // format mismatch or corruption: detect magic, re-download with correct decoder\n        std::fs::remove_file(&path).ok();\n        download_ffmpeg(...).await?;\n    },\n    r => r?,\n}","preventionTips":["Check the xz magic bytes before choosing XzDecoder","Track upstream FFmpeg release format changes (.tar.xz vs .tar.gz)","Compare Content-Length with actual bytes downloaded","Re-download rather than retry-extract on corruption"],"tags":["tar","xz","corrupt-archive"],"backgroundTag":"file-read-failed","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"}