{"record":{"id":"93f8d7903733853b","repo":"Zackriya-Solutions/meetily","slug":"download-already-in-progress-for-model-93f8d7","errorCode":null,"errorMessage":"Download already in progress for model: {}","messagePattern":"Download already in progress for model: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"frontend/src-tauri/src/whisper_engine/whisper_engine.rs","lineNumber":935,"sourceCode":"                {\n                    let mut models = self.available_models.write().await;\n                    if let Some(model) = models.get_mut(model_name) {\n                        model.status = ModelStatus::Missing;\n                    }\n                }\n\n                Ok(format!(\"Successfully deleted model '{}'\", model_name))\n            }\n            _ => {\n                Err(anyhow!(\"Can only delete corrupted or available models. Model '{}' has status: {:?}\", model_name, model_info.status))\n            }\n        }\n    }\n    \n    async fn reserve_active_download(&self, model_name: &str) -> Result<Arc<ActiveDownload>> {\n        let mut active_downloads = self.active_downloads.lock().await;\n        if active_downloads.contains_key(model_name) {\n            return Err(anyhow!(\"Download already in progress for model: {}\", model_name));\n        }\n\n        let (completion, _) = watch::channel(false);\n        let active_download = Arc::new(ActiveDownload {\n            cancellation: CancellationToken::new(),\n            completion,\n        });\n\n        active_downloads.insert(model_name.to_string(), Arc::clone(&active_download));\n        Ok(active_download)\n    }\n\n    async fn finish_download(\n        &self,\n        model_name: &str,\n        active_download: &Arc<ActiveDownload>,\n        file_path: &PathBuf,\n        mut result: Result<()>,","sourceCodeStart":917,"sourceCodeEnd":953,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/a2cb62e827da7ef59f65064c97233efb2313878e/frontend/src-tauri/src/whisper_engine/whisper_engine.rs#L917-L953","documentation":"download_model checks the active_downloads set at entry and rejects a second concurrent download of the same model name. This prevents two HTTP streams writing the same ggml-<name>.bin path simultaneously. The first download continues unaffected; the duplicate call fails immediately.","triggerScenarios":"Double-clicking the Download button before it disables; two UI components both invoking download_model for the same name; automatic retry logic firing while the first attempt still streams.","commonSituations":"Missing debounce on the download button; background auto-download racing a user-initiated download; optimistic-refresh frontend that re-issues the call.","solutions":["Wait for the in-flight download — subscribe to its progress events until 100 or completion","Disable the Download button while the model shows Downloading status","If the flag is stale because a prior call hung, cancel the download or restart the app, then retry"],"exampleFix":"// before\nbutton.onClick(() => invoke('download_model', { modelName })); // double-fire\n\n// after\nlet downloading = false;\nbutton.onClick(async () => {\n  if (downloading) return;\n  downloading = true;\n  try { await invoke('download_model', { modelName }); }\n  finally { downloading = false; }\n});","handlingStrategy":"validation","validationCode":"const models = await invoke<ModelInfo[]>('get_whisper_models');\nconst downloading = models.find(x => x.name === modelName)?.status === 'Downloading';\nif (downloading) {\n  // attach to the existing progress stream instead of starting a second one\n  return;\n}\nawait invoke('download_model', { modelName });","typeGuard":"const isDownloading = (m: ModelInfo | undefined): boolean => m?.status === 'Downloading';","tryCatchPattern":"try {\n  await invoke('download_model', { modelName });\n} catch (e) {\n  if (String(e).includes('already in progress')) {\n    // benign: join the existing download's progress events\n  } else { throw e; }\n}","preventionTips":["Debounce/disable the Download button from the first click until a terminal status arrives","Drive all download entry points (manual + auto) through one coordinator that checks active status","Treat 'already in progress' as info, not error, in telemetry"],"tags":["whisper","download","concurrency","rust","tauri"],"backgroundTag":"operation-already-in-progress","analyzedSha":"a2cb62e827da7ef59f65064c97233efb2313878e","analyzedAt":"2026-09-12T11:12:14.152Z","contentChangedAt":"2026-09-12T11:12:14.152Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}