cjpais/Handy · error · anyhow::Error

Model not found: {}

Error message

Model not found: {}

What it means

TranscriptionManager::load_model looks up model_id via ModelManager::get_model_info and got None — the id is not present in the local model registry/catalog at all. This fails before any filesystem or engine work; a loading_failed model-state event has already been emitted with the same id.

Source

Thrown at src-tauri/src/managers/transcription.rs:504

        let load_start = std::time::Instant::now();
        debug!("Starting to load model: {}", model_id);

        // Emit loading started event
        let _ = self.app_handle.emit(
            "model-state-changed",
            ModelStateEvent {
                event_type: "loading_started".to_string(),
                model_id: Some(model_id.to_string()),
                model_name: None,
                error: None,
            },
        );

        let model_info = self
            .model_manager
            .get_model_info(model_id)
            .ok_or_else(|| anyhow::anyhow!("Model not found: {}", model_id))?;

        if !model_info.is_downloaded {
            let error_msg = "Model not downloaded";
            let _ = self.app_handle.emit(
                "model-state-changed",
                ModelStateEvent {
                    event_type: "loading_failed".to_string(),
                    model_id: Some(model_id.to_string()),
                    model_name: Some(model_info.name.clone()),
                    error: Some(error_msg.to_string()),
                },
            );
            return Err(anyhow::anyhow!(error_msg));
        }

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

        // Drop the current engine BEFORE building the new one so transcribe-cpp

View on GitHub (pinned to 98a4d80cce)

Solutions

  1. Fetch the current catalog via get_available_models and select a valid id
  2. Reset the active model with set_active_model(<existing-id>)
  3. Run rescan_local_models to rebuild the registry, then retry
  4. Check for an exact id match — ids are case- and separator-sensitive

Example fix

// before
self.transcription_manager.load_model(model_id.clone()).await?;

// after
let known = self.model_manager.get_model_info(&model_id).is_some();
if !known {
    let models = self.model_manager.get_models();
    let fallback = models.iter().find(|m| m.is_downloaded)
        .ok_or_else(|| anyhow::anyhow!("No downloaded model available"))?;
    self.transcription_manager.load_model(fallback.id.clone()).await?;
} else {
    self.transcription_manager.load_model(model_id.clone()).await?;
}
Defensive patterns

Strategy: validation

Validate before calling

let models = model_manager.get_models(); // current catalog snapshot
let valid = models.iter().any(|m| m.id == model_id);
if !valid {
    // pick a downloaded fallback or refresh settings before loading
    let fallback = models.iter().find(|m| m.is_downloaded)
        .ok_or_else(|| anyhow::anyhow!("No downloaded model available"))?;
    set_active_model(fallback.id.clone()).await?;
    model_id = fallback.id.clone();
}

Type guard

fn is_known_model_id(mm: &ModelManager, id: &str) -> bool {
    mm.get_model_info(id).is_some()
}

Try / catch

match transcription_manager.load_model(model_id.clone()).await {
    Ok(()) => Ok(()),
    Err(e) if e.to_string().starts_with("Model not found") => {
        // stale setting: re-resolve against the live catalog and retry once
        let models = model_manager.get_models();
        let fallback = models.iter().find(|m| m.is_downloaded)
            .ok_or_else(|| anyhow::anyhow!("No downloaded model available"))?;
        transcription_manager.load_model(fallback.id.clone()).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Persisted settings point at a model id that no longer exists after an app update renamed or removed models; the frontend passes an id captured from a stale catalog; a typo'd or hand-crafted id; the model was deleted between listing and loading.

Common situations: App updates renaming model ids; settings restored from an older version; concurrent deletion from another window; custom model ids that were never registered.

Related errors


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