{"record":{"id":"1729d87c1dafe943","repo":"tonhowtf/omniget","slug":"ffmpeg-metadata-failed","errorCode":null,"errorMessage":"ffmpeg metadata failed: {}","messagePattern":"ffmpeg metadata failed: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/ffmpeg.rs","lineNumber":537,"sourceCode":"\n    args.push(temp_output.to_string_lossy().to_string());\n\n    let output = crate::core::process::command(\"ffmpeg\")\n        .args(&args)\n        .stdout(std::process::Stdio::piped())\n        .stderr(std::process::Stdio::piped())\n        .output()\n        .await\n        .map_err(|e| anyhow!(\"Failed to run ffmpeg: {}\", e))?;\n\n    if let Some(ref thumb) = thumbnail_path {\n        let _ = std::fs::remove_file(thumb);\n    }\n\n    if !output.status.success() {\n        let _ = std::fs::remove_file(&temp_output);\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        return Err(anyhow!(\"ffmpeg metadata failed: {}\", stderr));\n    }\n\n    let mut rename_ok = false;\n    for attempt in 0..3 {\n        match std::fs::rename(&temp_output, file) {\n            Ok(()) => {\n                rename_ok = true;\n                break;\n            }\n            Err(e) if attempt < 2 => {\n                tracing::warn!(\n                    \"Failed to replace file (attempt {}): {}, retrying...\",\n                    attempt + 1,\n                    e\n                );\n                tokio::time::sleep(std::time::Duration::from_millis(500 * (attempt as u64 + 1)))\n                    .await;\n            }","sourceCodeStart":519,"sourceCodeEnd":555,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/ffmpeg.rs#L519-L555","documentation":"After embed_metadata() runs ffmpeg, a non-zero exit status causes the captured stderr to be captured and returned as this error, and the temp output file is cleaned up. This is how ffmpeg's own failures (bad args, unreadable thumbnail, unsupported codec) surface to callers.","triggerScenarios":"Calling embed_metadata with an invalid metadata field value, a thumbnail URL that downloaded into a corrupt/unsupported image, or an output container that rejects one of the stream copy operations.","commonSituations":"Embedding a WebP thumbnail into MP4 (older ffmpeg lacks support); bad -metadata key/value strings with unescaped characters; disk full causing ffmpeg write errors; wrong -map arguments.","solutions":["Read the stderr in the error message — it names the exact ffmpeg failure (codec, map, I/O).","Validate the thumbnail image format/codec before embedding; convert to PNG/JPEG if needed.","Check free disk space in the target directory.","Test the exact ffmpeg command manually in a shell to reproduce and iterate on the arguments."],"exampleFix":"// before\nlet stderr = String::from_utf8_lossy(&output.stderr);\nreturn Err(anyhow!(\"ffmpeg metadata failed: {}\", stderr));\n// after\nlet stderr = String::from_utf8_lossy(&output.stderr);\nreturn Err(anyhow!(\n    \"ffmpeg metadata failed (exit {:?}): {}\",\n    output.status.code(),\n    stderr\n));","handlingStrategy":"try-catch","validationCode":"// validate thumbnail bytes are a decodable image before embedding\nlet kind = image::guess_format(&thumb_bytes)\n    .map_err(|_| \"thumbnail is not a recognized image format\")?;\nif !matches!(kind, image::ImageFormat::Jpeg | image::ImageFormat::Png) {\n    return Err(\"convert thumbnail to JPEG/PNG before embedding\".into());\n}","typeGuard":null,"tryCatchPattern":"match embed_metadata(/* ... */).await {\n    Err(e) if e.to_string().contains(\"ffmpeg metadata failed\") => {\n        let stderr = e.to_string();\n        if stderr.contains(\"Could not find tag\") || stderr.contains(\"codec\") {\n            log::warn!(\"unsupported embed target/thumbnail: {stderr}\");\n            // keep original file without embedded metadata\n        } else {\n            return Err(e);\n        }\n    }\n    other => other?,\n}","preventionTips":["Always read the stderr inside the error before deciding on a fallback","Pre-validate metadata key/value strings and thumbnail formats","Test the equivalent ffmpeg command in a shell when iterating on args","Check disk space before long embed operations"],"tags":["ffmpeg","nonzero-exit","stderr","metadata"],"backgroundTag":"http-error-response","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"}