{"record":{"id":"06ea8214b1480955","repo":"Zackriya-Solutions/meetily","slug":"can-only-delete-corrupted-or-available-models-mod","errorCode":null,"errorMessage":"Can only delete corrupted or available models. Model '{}' has status: {:?}","messagePattern":"Can only delete corrupted or available models\\. Model '(.+?)' has status: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"frontend/src-tauri/src/whisper_engine/whisper_engine.rs","lineNumber":892,"sourceCode":"                    fs::remove_file(&model_info.path).await\n                        .map_err(|e| anyhow!(\"Failed to delete file '{}': {}\", model_info.path.display(), e))?;\n                    log::info!(\"Successfully deleted available model file: {}\", model_info.path.display());\n                } else {\n                    log::warn!(\"File '{}' does not exist, nothing to delete\", model_info.path.display());\n                }\n\n                // Update model status to Missing\n                {\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    pub async fn download_model(&self, model_name: &str, progress_callback: Option<Box<dyn Fn(u8) + Send>>) -> Result<()> {\n        log::info!(\"Starting download for model: {}\", model_name);\n\n        // Check if download is already in progress for this model\n        {\n            let active = self.active_downloads.read().await;\n            if active.contains(model_name) {\n                log::warn!(\"Download already in progress for model: {}\", model_name);\n                return Err(anyhow!(\"Download already in progress for model: {}\", model_name));\n            }\n        }\n\n        // Add to active downloads\n        {","sourceCodeStart":874,"sourceCodeEnd":910,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/whisper_engine/whisper_engine.rs#L874-L910","documentation":"delete_model only handles ModelStatus::Corrupted and ModelStatus::Available; every other status falls to the catch-all arm and is rejected with the current status shown. This is a deliberate state-machine guard: you cannot delete what is Missing (nothing on disk), Downloading (an active task owns the file), or Error (recover by re-downloading instead).","triggerScenarios":"Calling delete_model while download_model streams the same model (Downloading); double-delete where the first call already set status Missing; calling delete on a model whose status is Error.","commonSituations":"User hits Delete during an active download; UI row not refreshed after a delete so the action fires twice; trying to 'clear' an Error state by deleting it.","solutions":["For Downloading: cancel the download first (set the cancel flag / cancel_download command) or wait for it to finish, then delete","For Missing: nothing to delete — refresh the model list; the action already succeeded earlier","For Error: re-run download_model to overwrite the bad file instead of deleting, or remove the file manually and rescan"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const models = await invoke<ModelInfo[]>('get_whisper_models');\nconst m = models.find(x => x.name === modelName);\nif (!m) throw new Error('Unknown model');\nif (m.status !== 'Available' && m.status !== 'Corrupted') {\n  throw new Error(`Cannot delete while status is ${m.status}. Cancel the download or refresh.`);\n}\nawait invoke('delete_model', { modelName });","typeGuard":"const isDeletable = (s: string): boolean => s === 'Available' || s === 'Corrupted';","tryCatchPattern":"try {\n  await invoke('delete_model', { modelName });\n} catch (e) {\n  if (String(e).includes('Can only delete')) {\n    // Downloading -> cancel first; Missing -> refresh list; Error -> re-download instead\n    refreshModelList();\n  } else { throw e; }\n}","preventionTips":["Hide or disable Delete for rows whose status is not Available/Corrupted","Cancel an active download before offering deletion of the same model","Refresh the model list after every delete/cancel to prevent stale-row double actions"],"tags":["whisper","model-management","state-machine","rust"],"backgroundTag":"invalid-state-transition","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}