Zackriya-Solutions/meetily · error · anyhow::Error
Failed to delete file '{}': {}
Error message
Failed to delete file '{}': {} What it means
In delete_model's Corrupted branch, tokio fs::remove_file on the model path failed and the OS error is appended. The path in the message plus the errno identify the blocker: PermissionDenied (locked or read-only), NotFound (already gone), or IsADirectory. The status is not reset to Missing when this fires.
Source
Thrown at frontend/src-tauri/src/whisper_engine/whisper_engine.rs:853
// Get model info to find the file path
let model_info = {
let models = self.available_models.read().await;
models.get(model_name).cloned()
};
let model_info = model_info.ok_or_else(|| anyhow!("Model '{}' not found", model_name))?;
// Check if model is corrupted before allowing deletion
log::info!("Model '{}' has status: {:?}", model_name, model_info.status);
match &model_info.status {
ModelStatus::Corrupted { file_size, expected_min_size } => {
log::info!("Deleting corrupted model '{}' (file size: {} bytes, expected min: {} bytes)",
model_name, file_size, expected_min_size);
// Delete the file
if model_info.path.exists() {
fs::remove_file(&model_info.path).await
.map_err(|e| anyhow!("Failed to delete file '{}': {}", model_info.path.display(), e))?;
log::info!("Successfully deleted corrupted file: {}", model_info.path.display());
} else {
log::warn!("File '{}' does not exist, nothing to delete", model_info.path.display());
}
// Update model status to Missing
{
let mut models = self.available_models.write().await;
if let Some(model) = models.get_mut(model_name) {
model.status = ModelStatus::Missing;
}
}
Ok(format!("Successfully deleted corrupted model '{}'", model_name))
}
ModelStatus::Available => {
// Allow deletion of available models for testing/cleanup
log::info!("Deleting available model '{}' (for cleanup)", model_name);View on GitHub (pinned to 0281737d87)
Solutions
- Call unload_model before delete_model so no open file handle remains
- Close other app instances and wait a few seconds for antivirus scans to release the file, then retry
- Fix permissions on the models directory (remove read-only flag, verify ownership) and retry
- As a last resort, delete ggml-<name>.bin manually and rescan models
Defensive patterns
Strategy: retry
Validate before calling
// Unload first so no open handle remains, then delete
await invoke('unload_whisper_model');
await invoke('delete_model', { modelName }); Try / catch
for (let attempt = 1; attempt <= 3; attempt++) {
try {
await invoke('delete_model', { modelName });
break;
} catch (e) {
if (String(e).includes('Failed to delete file') && attempt < 3) {
await sleep(1000 * attempt); // AV/lock usually clears; retry
} else { throw e; }
}
} Prevention
- Call unload_model before deleting any model file, especially on Windows
- Run a single app instance; cloud-sync and AV clients are common file-lock sources in the models dir
- Show the OS error string to the user — PermissionDenied vs NotFound need different actions
When it happens
Trigger: Windows file lock: another process (antivirus, a still-loaded whisper context, second app instance) holds an open handle on the ggml file; read-only file permissions; models dir on a volume unmounted mid-operation.
Common situations: Windows delete-after-load flows where the model context was never unloaded; corporate machines with AV scanning new .bin files; models stored on external/network drives.
Related errors
- Failed to create models directory: {}
- Model {} is corrupted and cannot be loaded
- Failed to create file: {}
- Cannot read file: {}
- Whisper transcription failed on segment {}: {}
AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16).
Data as JSON: /api/errors/a730a64c9445bde0.
Report an issue: GitHub.