Zackriya-Solutions/meetily · error · anyhow::Error

Failed to replace {}: {}

Error message

Failed to replace {}: {}

What it means

This error is raised by the Parakeet model-download code in parakeet_engine.rs when creating/truncating the destination file for a fresh (non-resume) download fails. `fs::OpenOptions::new().create(true).truncate(true).write(true).open(&file_path)` could not open the target artifact file, so the buffered writer cannot be constructed and the download aborts. The underlying OS error is embedded in the message after the filename, which is the real diagnostic.

Source

Thrown at frontend/src-tauri/src/parakeet_engine/parakeet_engine.rs:991

            };

            if active_download.cancellation.is_cancelled() {
                return Err(DownloadCancelled.into());
            }
            let file = if append {
                fs::OpenOptions::new()
                    .append(true)
                    .open(&file_path)
                    .await
                    .map_err(|error| anyhow!("Failed to open {} for resume: {}", artifact.filename, error))?
            } else {
                fs::OpenOptions::new()
                    .create(true)
                    .truncate(true)
                    .write(true)
                    .open(&file_path)
                    .await
                    .map_err(|error| anyhow!("Failed to replace {}: {}", artifact.filename, error))?
            };
            let mut writer = BufWriter::with_capacity(8 * 1024 * 1024, file);
            use futures_util::StreamExt;
            let mut stream = response.bytes_stream();

            loop {
                let next_chunk = tokio::select! {
                    biased;
                    _ = active_download.cancellation.cancelled() => {
                        writer.flush().await.map_err(|error| {
                            anyhow!("Failed to preserve {} during cancellation: {}", artifact.filename, error)
                        })?;
                        return Err(DownloadCancelled.into());
                    }
                    chunk = timeout(Duration::from_secs(30), stream.next()) => chunk,
                };
                let chunk = match next_chunk {
                    Err(_) => {

View on GitHub (pinned to a2cb62e827)

Solutions

  1. Read the underlying OS error after the second `{}` in the message and fix it directly (e.g. NotFound → create the parent models directory, PermissionDenied → fix permissions or move the models dir to a writable location).
  2. Ensure the models directory exists before downloading (call `fs::create_dir_all` on the artifacts directory, or use Tauri's `app_data_dir`/`app_local_data_dir` path API instead of a hardcoded path).
  3. Check free disk space — model files are hundreds of MB to GB; delete stale/partial artifacts and retry.
  4. Verify the target path is not a directory and no other process (editor, antivirus quarantine, previous app instance) holds the file; close/rename it and retry.
  5. If running from a restricted location, reinstall or relocate the app so its data directory is user-writable.

Example fix

// before
let file = fs::OpenOptions::new()
    .create(true).truncate(true).write(true)
    .open(&file_path)
    .await
    .map_err(|error| anyhow!("Failed to replace {}: {}", artifact.filename, error))?;

// after: guarantee the parent directory exists first
if let Some(parent) = file_path.parent() {
    fs::create_dir_all(parent).await
        .map_err(|error| anyhow!("Failed to create models dir {}: {}", parent.display(), error))?;
}
let file = fs::OpenOptions::new()
    .create(true).truncate(true).write(true)
    .open(&file_path)
    .await
    .map_err(|error| anyhow!("Failed to replace {}: {}", artifact.filename, error))?;
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;

async fn ensure_writable_target(path: &Path) -> Result<(), String> {
    let parent = path.parent().ok_or("target has no parent dir")?;
    if !parent.exists() {
        tokio::fs::create_dir_all(parent).await.map_err(|e| e.to_string())?;
    }
    if path.is_dir() {
        return Err(format!("{} is a directory", path.display()));
    }
    // probe writability with a cheap open
    tokio::fs::OpenOptions::new()
        .create(true).append(true)
        .open(path).await
        .map(|_| ())
        .map_err(|e| format!("cannot write {}: {}", path.display(), e))
}

Try / catch

match engine.download_models(&artifacts, &token).await {
    Err(e) if e.to_string().starts_with("Failed to replace ") => {
        // inspect the trailing OS io::Error, ensure dirs/permissions, then retry once
        ensure_writable_target(&models_dir.join(&artifact.filename)).await?;
        engine.download_models(&artifacts, &token).await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Occurs during a full (non-append) download of a Parakeet model artifact when `tokio::fs::OpenOptions` open() fails: the models directory does not exist, the process lacks write permission on the path, the path is invalid or too long for the platform, the path is a directory, the file is locked/opened by another process, disk is full, or on Windows the file is held by antivirus.

Common situations: First launch before the models directory (`frontend/models/` in dev, `~/Library/Application Support/Meetily/models/` on macOS, `%APPDATA%\Meetily\models/` on Windows) was created; running the app from a read-only install location or a location lacking Tauri's expected app-data permissions; a previous crash left a partially-written artifact locked by an indexing/AV process; disk full after a large model partially downloaded.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@a2cb62e827 (2026-09-12). Data as JSON: /api/errors/36855003069566d8. Report an issue: GitHub.