cjpais/Handy · error · anyhow::Error

Model not available

Error message

Model not available: {}

What it means

The model entry exists but is_downloaded is false, so get_model_path refuses to hand out a path — there is nothing on disk to transcribe with. This is a state/ordering error: the caller asked to use a model before it was downloaded (or after a failed/rolled-back download).

Solutions

  1. Trigger downloadModel and wait for the model-download-complete event before enabling recording
  2. Restrict the model selector in settings to entries with is_downloaded true
  3. If it just completed, refresh model status — the flag updates via update_download_status

Example fix

// before (TS) — start recording regardless of model state
await startRecording();

// after — gate recording on the selected model being ready
const info = await commands.getModelInfo(selectedModelId);
if (info.status === "ok" && !info.data.is_downloaded) {
  await commands.downloadModel(selectedModelId);
  // wait for the model-download-complete event before proceeding
}
await startRecording();
Defensive patterns

Strategy: validation

Validate before calling

// gate on download state before resolving the path
let info = manager.get_model_info(model_id)
    .ok_or_else(|| anyhow::anyhow!("Model not found: {model_id}"))?;
if !info.is_downloaded {
    manager.download_model(model_id).await?; // caller waits for model-download-complete
}

Try / catch

match manager.get_model_path(id) {
    Err(e) if e.to_string().contains("Model not available") => {
        // trigger download and surface 'model not ready' to the user — do not transcribe
    }
    other => other,
}

Prevention

When it happens

Trigger: Recording started before the selected model finished downloading; a previous download failed so the flag stayed false; is_downloaded not yet refreshed after completion (event race between model-download-complete and the status map).

Common situations: Onboarding flow letting users record before the first model download completes; model switch to a not-yet-downloaded model; settings restored on a new machine where models dir is empty.

Related errors


AI-assisted analysis of cjpais/Handy@ba10ce1943 (2026-08-17). Data as JSON: /api/errors/420357d55ccb4dfe. Report an issue: GitHub.

Appendix: source

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

        if removed {
            info!("Removing vanished discovered model '{}'", model_id);
        } else {
            info!("Marking model '{}' as unavailable on disk", model_id);
        }
        // Keep the persisted preference here: an already-loaded engine may
        // still be usable, and re-downloading this model should restore it.
        // Startup and explicit Rescan perform the broader selection cleanup.
        let _ = self.app_handle.emit("models-updated", ());
    }

    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.

View on GitHub (pinned to ba10ce1943)