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

Can only delete corrupted or available models. Model '{}' ha

Error message

Can only delete corrupted or available models. Model '{}' has status: {:?}

What it means

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).

Source

Thrown at frontend/src-tauri/src/whisper_engine/whisper_engine.rs:892

                    fs::remove_file(&model_info.path).await
                        .map_err(|e| anyhow!("Failed to delete file '{}': {}", model_info.path.display(), e))?;
                    log::info!("Successfully deleted available model 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 model '{}'", model_name))
            }
            _ => {
                Err(anyhow!("Can only delete corrupted or available models. Model '{}' has status: {:?}", model_name, model_info.status))
            }
        }
    }
    
    pub async fn download_model(&self, model_name: &str, progress_callback: Option<Box<dyn Fn(u8) + Send>>) -> Result<()> {
        log::info!("Starting download for model: {}", model_name);

        // Check if download is already in progress for this model
        {
            let active = self.active_downloads.read().await;
            if active.contains(model_name) {
                log::warn!("Download already in progress for model: {}", model_name);
                return Err(anyhow!("Download already in progress for model: {}", model_name));
            }
        }

        // Add to active downloads
        {

View on GitHub (pinned to 0281737d87)

Solutions

  1. For Downloading: cancel the download first (set the cancel flag / cancel_download command) or wait for it to finish, then delete
  2. For Missing: nothing to delete — refresh the model list; the action already succeeded earlier
  3. For Error: re-run download_model to overwrite the bad file instead of deleting, or remove the file manually and rescan
Defensive patterns

Strategy: validation

Validate before calling

const models = await invoke<ModelInfo[]>('get_whisper_models');
const m = models.find(x => x.name === modelName);
if (!m) throw new Error('Unknown model');
if (m.status !== 'Available' && m.status !== 'Corrupted') {
  throw new Error(`Cannot delete while status is ${m.status}. Cancel the download or refresh.`);
}
await invoke('delete_model', { modelName });

Type guard

const isDeletable = (s: string): boolean => s === 'Available' || s === 'Corrupted';

Try / catch

try {
  await invoke('delete_model', { modelName });
} catch (e) {
  if (String(e).includes('Can only delete')) {
    // Downloading -> cancel first; Missing -> refresh list; Error -> re-download instead
    refreshModelList();
  } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/06ea8214b1480955. Report an issue: GitHub.