{"record":{"id":"649f334c5abcc644","repo":"tonhowtf/omniget","slug":"failed-to-replace-file","errorCode":null,"errorMessage":"Failed to replace file","messagePattern":"Failed to replace file","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/ffmpeg.rs","lineNumber":564,"sourceCode":"            }\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            }\n            Err(e) => {\n                let _ = std::fs::remove_file(&temp_output);\n                return Err(anyhow!(\"Failed to replace file after 3 attempts: {}\", e));\n            }\n        }\n    }\n    if !rename_ok {\n        let _ = std::fs::remove_file(&temp_output);\n        return Err(anyhow!(\"Failed to replace file\"));\n    }\n\n    Ok(())\n}\n\nasync fn download_thumbnail(\n    client: &reqwest::Client,\n    url: &str,\n    dest_dir: &Path,\n) -> anyhow::Result<std::path::PathBuf> {\n    let response = client\n        .get(url)\n        .send()\n        .await\n        .map_err(|e| anyhow!(\"Failed to download thumbnail: {}\", e))?;\n\n    let content_type = response\n        .headers()","sourceCodeStart":546,"sourceCodeEnd":582,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/ffmpeg.rs#L546-L582","documentation":"After the 3-attempt rename loop, embed_metadata() checks a rename_ok flag. If all attempts returned Ok(()) from fs::rename but the flag was never set true (the loop's success path logs/sets flags but a code path left it false), this error fires and the temp file is removed. It is a defensive invariant check on the retry loop.","triggerScenarios":"The retry loop exhausts attempts where each rename returned Ok but did not set rename_ok=true (a logic bug), or a future refactor introduces a break/continue that skips setting the flag — the invariant check then trips.","commonSituations":"Surfacing during code changes to the retry loop rather than in normal operation; extremely rare in the wild because a successful rename sets the flag on the first attempt.","solutions":["Inspect the rename loop: every Ok(()) branch must set rename_ok = true (or restructure to return directly on success).","Prefer returning Ok(()) immediately inside the successful rename branch instead of tracking a flag.","If reproduced at runtime, verify no concurrent task renames the same temp file concurrently.","Add a unit test covering the loop's Ok and Err paths to keep the invariant intact."],"exampleFix":"// before\nif !rename_ok {\n    let _ = std::fs::remove_file(&temp_output);\n    return Err(anyhow!(\"Failed to replace file\"));\n}\n// after\n// in the retry loop, return directly on success instead of a flag:\nOk(()) => {\n    let _ = std::fs::remove_file(&temp_output).ok(); // nothing to clean\n    return Ok(());\n}\n// then the trailing unreachable check can be removed entirely","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match embed_metadata(/* ... */).await {\n    Err(e) if e.to_string() == \"Failed to replace file\" => {\n        // invariant trip in the rename loop; report with debug info\n        report_internal_bug(e);\n    }\n    other => other?,\n}","preventionTips":["Return directly from the success branch of the rename loop instead of a flag","Unit-test both Ok and Err paths of the rename retry loop","Never mutate the rename loop's control flow without re-checking the trailing guard"],"tags":["ffmpeg","file-rename","invariant","retry-logic"],"backgroundTag":"internal-invariant-violation","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"}