{"record":{"id":"48d95970cc32e061","repo":"tonhowtf/omniget","slug":"ffprobe-failed","errorCode":null,"errorMessage":"ffprobe failed: {}","messagePattern":"ffprobe failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/ffmpeg.rs","lineNumber":134,"sourceCode":"    let output = crate::core::process::command(\"ffprobe\")\n        .args([\n            \"-v\",\n            \"quiet\",\n            \"-print_format\",\n            \"json\",\n            \"-show_format\",\n            \"-show_streams\",\n            &path.to_string_lossy(),\n        ])\n        .stdout(std::process::Stdio::piped())\n        .stderr(std::process::Stdio::piped())\n        .output()\n        .await\n        .map_err(|e| anyhow!(\"Failed to run ffprobe: {}\", e))?;\n\n    if !output.status.success() {\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        return Err(anyhow!(\"ffprobe failed: {}\", stderr));\n    }\n\n    let json: serde_json::Value = serde_json::from_slice(&output.stdout)\n        .map_err(|e| anyhow!(\"Failed to parse ffprobe JSON: {}\", e))?;\n\n    let format = json\n        .get(\"format\")\n        .ok_or_else(|| anyhow!(\"Missing 'format' field\"))?;\n\n    let duration_seconds = format\n        .get(\"duration\")\n        .and_then(|v| v.as_str())\n        .and_then(|s| s.parse::<f64>().ok())\n        .unwrap_or(0.0);\n\n    let format_name = format\n        .get(\"format_name\")\n        .and_then(|v| v.as_str())","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/ffmpeg.rs#L116-L152","documentation":"probe launched ffprobe successfully, but it exited with a non-zero status; the error message includes ffprobe's captured stderr for diagnosis. This is the standard signal that ffprobe could not parse/inspect the given media file. Callers get_duration_us and convert propagate this failure.","triggerScenarios":"Calling probe on a file ffprobe cannot handle: nonexistent path, empty or truncated download (.part file), unsupported/corrupt container, or a path ffprobe can't read (permissions).","commonSituations":"Probing a file before a download finished (still .part); interrupted download left a truncated file; probing a path with broken permissions; probing HTML error pages saved as media files; DRM-protected or exotic codecs.","solutions":["Read the stderr in the error message — it names the exact codec/container problem (e.g. 'Invalid data found when processing input').","Verify the input file exists, is non-empty, and download completed (not a .part file) before calling probe.","Re-download the media if it's truncated or corrupt.","Check file read permissions and that the path is a regular file; update ffmpeg/ffprobe for newer formats."],"exampleFix":"// before\nif !output.status.success() {\n    let stderr = String::from_utf8_lossy(&output.stderr);\n    return Err(anyhow!(\"ffprobe failed: {}\", stderr));\n}\n// after — validate the input before probing\nif !path.exists() || metadata.len() == 0 {\n    return Err(anyhow!(\"cannot probe missing or empty file: {}\", path.display()));\n}\nif !output.status.success() {\n    let stderr = String::from_utf8_lossy(&output.stderr);\n    return Err(anyhow!(\"ffprobe failed ({}): {}\", output.status, stderr));\n}","handlingStrategy":"validation","validationCode":"// Validate the media file before asking ffprobe to parse it\nlet md = tokio::fs::metadata(path).await?;\nif !md.is_file() { bail!(\"not a file: {}\", path.display()); }\nif md.len() == 0 { bail!(\"empty file: {}\", path.display()); }\n// Optionally skip files still being written:\nif path.extension().map_or(false, |e| e == \"part\") { bail!(\"download still in progress: {}\", path.display()); }","typeGuard":null,"tryCatchPattern":"// The library already embeds ffprobe's stderr — surface it to the user and classify common cases\nmatch probe(path).await {\n    Err(e) if e.to_string().contains(\"ffprobe failed\") => {\n        let msg = e.to_string();\n        if msg.contains(\"Invalid data found\") || msg.contains(\"No such file\") {\n            Err(anyhow!(\"file is corrupt, truncated, or not a media file: {msg}\"))\n        } else {\n            Err(e)\n        }\n    }\n    other => other,\n}","preventionTips":["Only probe files whose download has fully completed — never .part or in-flight files.","Check file existence and non-zero size before probing; an HTML error page saved as .mp4 will fail here.","Surface the stderr text (already included in the error) — it pinpoints the codec/container problem.","Re-download media that fails probing rather than feeding truncated files downstream to convert/get_duration_us.","Keep ffmpeg/ffprobe updated for newer codecs and containers."],"tags":["ffprobe","exit-code","media-inspection","rust"],"backgroundTag":"process-exit-nonzero","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"}