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

Can only delete corrupted or available Parakeet models. Mode

Error message

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

What it means

Returned by delete_model for any status other than Corrupted or Available. The match arm intentionally refuses to delete models that are Missing (nothing on disk to remove), Downloading (an active task is writing files), or Error (not in a deletable state per this state machine), so the status enum value is echoed back in the message.

Source

Thrown at frontend/src-tauri/src/parakeet_engine/parakeet_engine.rs:519

                    fs::remove_dir_all(&model_info.path).await
                        .map_err(|e| anyhow!("Failed to delete directory '{}': {}", model_info.path.display(), e))?;
                    log::info!("Successfully deleted Parakeet model directory: {}", model_info.path.display());
                } else {
                    log::warn!("Directory '{}' 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 Parakeet model '{}'", model_name))
            }
            _ => {
                Err(anyhow!(
                    "Can only delete corrupted or available Parakeet models. Model '{}' has status: {:?}",
                    model_name,
                    model_info.status
                ))
            }
        }
    }

    /// Download a Parakeet model from HuggingFace (backward-compatible wrapper)
    pub async fn download_model(
        &self,
        model_name: &str,
        progress_callback: Option<Box<dyn Fn(u8) + Send>>,
    ) -> Result<()> {
        // Wrap simple callback to use detailed version
        let detailed_callback: Option<Box<dyn Fn(DownloadProgress) + Send>> =
            progress_callback.map(|cb| {
                Box::new(move |p: DownloadProgress| cb(p.percent)) as Box<dyn Fn(DownloadProgress) + Send>

View on GitHub (pinned to 0281737d87)

Solutions

  1. If Downloading: call parakeet_cancel_download / engine.cancel_download first, wait for the task to unwind, then delete (files will be gone or deletable)
  2. If Missing: nothing to delete - refresh the model list; the row should show as not downloaded
  3. If Error: re-attempt the download once so status transitions, or restart the app to re-discover, then delete
  4. Gate the delete button in the UI on status being Available or Corrupted

Example fix

// before
engine.delete_model(name).await?;

// after - only delete in a deletable state, cancel active downloads first
let status = engine.discover_models().await?
    .into_iter().find(|m| m.name == name).map(|m| m.status);
match status {
    Some(ModelStatus::Downloading { .. }) => { engine.cancel_download(&name).await?; }
    Some(ModelStatus::Corrupted { .. }) | Some(ModelStatus::Available) => {
        engine.delete_model(&name).await?;
    }
    _ => { /* nothing deletable */ }
}
Defensive patterns

Strategy: validation

Validate before calling

// Only offer deletion in states that support it; cancel active downloads first
let status = engine.discover_models().await?
    .into_iter().find(|m| m.name == name).map(|m| m.status);
match status {
    Some(ModelStatus::Downloading { .. }) => engine.cancel_download(&name).await?,
    Some(ModelStatus::Available) | Some(ModelStatus::Corrupted { .. }) => { /* safe to delete */ }
    other => anyhow::bail!("not deletable in state {other:?}"),
}

Type guard

fn is_deletable(info: &ModelInfo) -> bool {
    matches!(info.status, ModelStatus::Available | ModelStatus::Corrupted { .. })
}

Try / catch

try {
  await invoke('parakeet_delete_corrupted_model', { modelName });
} catch (e) {
  if (String(e).includes('Can only delete')) {
    // state problem, not a failure: cancel download or refresh list, never blind-retry
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling delete_model while download_model_detailed is streaming for that model (status Downloading); calling delete on a model already deleted/reset to Missing; calling delete on a model stuck in Error status expecting cleanup.

Common situations: User hits 'delete' on a model row whose download is still running; double-delete after a failed download left status Missing; UI delete button enabled for all rows regardless of state.

Related errors


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