cjpais/Handy · warning · anyhow::Error

Model is currently downloading: {}

Error message

Model is currently downloading: {}

What it means

Thrown by ModelManager::get_model_path when the model's registry entry has is_downloading=true. The manager refuses to hand out a path while a download task is active so callers never receive a half-written file; the guard also fires for partial files and directories. The main caller is TranscriptionManager::load_model, which calls get_model_path at transcription.rs:520.

Source

Thrown at src-tauri/src/managers/model.rs:2484

        // Emit event to notify UI
        let _ = self.app_handle.emit("model-deleted", model_id);

        Ok(())
    }

    pub fn get_model_path(&self, model_id: &str) -> Result<PathBuf> {
        let model_info = self
            .get_model_info(model_id)
            .ok_or_else(|| anyhow::anyhow!("Model not found: {}", model_id))?;

        if !model_info.is_downloaded {
            return Err(anyhow::anyhow!("Model not available: {}", model_id));
        }

        // Ensure we don't return partial files/directories
        if model_info.is_downloading {
            return Err(anyhow::anyhow!(
                "Model is currently downloading: {}",
                model_id
            ));
        }

        if let ModelSource::HuggingFace { repo_id, revision } = &model_info.source {
            if let Some(path) = hf_cached_path(repo_id, revision, &model_info.filename) {
                return Ok(path);
            }
            // Mirror-fallback download or manual drop-in in the models dir.
            // The complete file only ever appears after verification, so a
            // stale `.partial` alongside it is leftover noise, not a veto —
            // clear it rather than declaring the model missing.
            let local_path = self.models_dir.join(&model_info.filename);
            if local_path.exists() {
                let partial_path = self
                    .models_dir
                    .join(format!("{}.partial", &model_info.filename));

View on GitHub (pinned to 98a4d80cce)

Solutions

  1. Wait for the model-state-changed / download completion event before loading or calling get_model_path
  2. Pre-check with get_model_info(model_id) and skip while is_downloading is true; show a 'downloading' UI state instead
  3. If the flag is stale after a crash, restart the app (state is rebuilt from disk) or call cancel_download(model_id) to clear it, then retry
  4. Run rescan_local_models to rebuild the registry's download state from the filesystem

Example fix

// before
let model_path = self.model_manager.get_model_path(model_id)?;

// after
let info = self.model_manager.get_model_info(model_id)
    .ok_or_else(|| anyhow::anyhow!("Model not found: {}", model_id))?;
if info.is_downloading {
    // wait for the download-completed event instead of failing here
    return Ok(());
}
let model_path = self.model_manager.get_model_path(model_id)?;
Defensive patterns

Strategy: validation

Validate before calling

let Some(info) = model_manager.get_model_info(model_id) else {
    anyhow::bail!("Model not found: {}", model_id);
};
if info.is_downloading {
    // Skip loading now; subscribe to the model-state-changed event
    // and retry once the download-completed event arrives.
    return Ok(WaitOutcome::Downloading(info.partial_size));
}
let path = model_manager.get_model_path(model_id)?;

Type guard

fn is_model_path_ready(mm: &ModelManager, id: &str) -> bool {
    mm.get_model_info(id)
        .map(|i| i.is_downloaded && !i.is_downloading)
        .unwrap_or(false)
}

Try / catch

match model_manager.get_model_path(model_id) {
    Ok(path) => Ok(path),
    Err(e) if e.to_string().starts_with("Model is currently downloading") => {
        // transient: wait for the download-completed event, then retry once
        wait_for_model_event("download completed", model_id).await?;
        model_manager.get_model_path(model_id)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling get_model_path(model_id), or the transcription load path that wraps it, while download_model for the same id is still in flight — e.g. the user selects a model right after starting its download, or startup auto-load races an in-progress download.

Common situations: Race between the 'download started' state and a load request; a stuck is_downloading flag after the app was killed mid-download (the RAII cleanup guard in model.rs never ran); retry logic that immediately loads after enqueueing a download.

Related errors


AI-assisted analysis of cjpais/Handy@98a4d80cce (2026-08-16). Data as JSON: /api/errors/403f957bf542ebff. Report an issue: GitHub.