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
- 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).
- 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).
- Check free disk space — model files are hundreds of MB to GB; delete stale/partial artifacts and retry.
- 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.
- 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
- Always create the models directory (via create_dir_all or Tauri's app_data_dir API) before triggering downloads
- Never hardcode model paths; use Tauri path APIs so the dir is user-writable on every platform
- Check free disk space (hundreds of MB–GB per model) before starting a download
- Don't place the models folder on removable/network drives
- Clean up stale partial artifacts after crashes so no locked file blocks the fresh open
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
- Failed to preserve {} during cancellation: {}
- Failed to read downloaded model file metadata: {}
- Failed to create file {}: {}
- Failed to write chunk to file: {}
- Failed to flush file {}: {}
AI-assisted analysis of Zackriya-Solutions/meetily@a2cb62e827 (2026-09-12).
Data as JSON: /api/errors/36855003069566d8.
Report an issue: GitHub.