tonhowtf/omniget · error · anyhow::Error

Failed to replace file

Error message

Failed to replace file

What it means

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.

Solutions

  1. Inspect the rename loop: every Ok(()) branch must set rename_ok = true (or restructure to return directly on success).
  2. Prefer returning Ok(()) immediately inside the successful rename branch instead of tracking a flag.
  3. If reproduced at runtime, verify no concurrent task renames the same temp file concurrently.
  4. Add a unit test covering the loop's Ok and Err paths to keep the invariant intact.

Example fix

// before
if !rename_ok {
    let _ = std::fs::remove_file(&temp_output);
    return Err(anyhow!("Failed to replace file"));
}
// after
// in the retry loop, return directly on success instead of a flag:
Ok(()) => {
    let _ = std::fs::remove_file(&temp_output).ok(); // nothing to clean
    return Ok(());
}
// then the trailing unreachable check can be removed entirely
Defensive patterns

Strategy: try-catch

Try / catch

match embed_metadata(/* ... */).await {
    Err(e) if e.to_string() == "Failed to replace file" => {
        // invariant trip in the rename loop; report with debug info
        report_internal_bug(e);
    }
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/649f334c5abcc644. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/ffmpeg.rs:564

            }
            Err(e) if attempt < 2 => {
                tracing::warn!(
                    "Failed to replace file (attempt {}): {}, retrying...",
                    attempt + 1,
                    e
                );
                tokio::time::sleep(std::time::Duration::from_millis(500 * (attempt as u64 + 1)))
                    .await;
            }
            Err(e) => {
                let _ = std::fs::remove_file(&temp_output);
                return Err(anyhow!("Failed to replace file after 3 attempts: {}", e));
            }
        }
    }
    if !rename_ok {
        let _ = std::fs::remove_file(&temp_output);
        return Err(anyhow!("Failed to replace file"));
    }

    Ok(())
}

async fn download_thumbnail(
    client: &reqwest::Client,
    url: &str,
    dest_dir: &Path,
) -> anyhow::Result<std::path::PathBuf> {
    let response = client
        .get(url)
        .send()
        .await
        .map_err(|e| anyhow!("Failed to download thumbnail: {}", e))?;

    let content_type = response
        .headers()

View on GitHub (pinned to 8600b91f42)