{"record":{"id":"bb30d03c4c33ec35","repo":"cjpais/Handy","slug":"model-not-found-bb30d0","errorCode":null,"errorMessage":"Model not found: {}","messagePattern":"Model not found: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/transcription.rs","lineNumber":504,"sourceCode":"\n        let load_start = std::time::Instant::now();\n        debug!(\"Starting to load model: {}\", model_id);\n\n        // Emit loading started event\n        let _ = self.app_handle.emit(\n            \"model-state-changed\",\n            ModelStateEvent {\n                event_type: \"loading_started\".to_string(),\n                model_id: Some(model_id.to_string()),\n                model_name: None,\n                error: None,\n            },\n        );\n\n        let model_info = self\n            .model_manager\n            .get_model_info(model_id)\n            .ok_or_else(|| anyhow::anyhow!(\"Model not found: {}\", model_id))?;\n\n        if !model_info.is_downloaded {\n            let error_msg = \"Model not downloaded\";\n            let _ = self.app_handle.emit(\n                \"model-state-changed\",\n                ModelStateEvent {\n                    event_type: \"loading_failed\".to_string(),\n                    model_id: Some(model_id.to_string()),\n                    model_name: Some(model_info.name.clone()),\n                    error: Some(error_msg.to_string()),\n                },\n            );\n            return Err(anyhow::anyhow!(error_msg));\n        }\n\n        let model_path = self.model_manager.get_model_path(model_id)?;\n\n        // Drop the current engine BEFORE building the new one so transcribe-cpp","sourceCodeStart":486,"sourceCodeEnd":522,"githubUrl":"https://github.com/cjpais/Handy/blob/98a4d80cce8ad41efec2a419b59d9e81229a35d7/src-tauri/src/managers/transcription.rs#L486-L522","documentation":"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.","triggerScenarios":"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.","commonSituations":"App updates renaming model ids; settings restored from an older version; concurrent deletion from another window; custom model ids that were never registered.","solutions":["Fetch the current catalog via get_available_models and select a valid id","Reset the active model with set_active_model(<existing-id>)","Run rescan_local_models to rebuild the registry, then retry","Check for an exact id match — ids are case- and separator-sensitive"],"exampleFix":"// before\nself.transcription_manager.load_model(model_id.clone()).await?;\n\n// after\nlet known = self.model_manager.get_model_info(&model_id).is_some();\nif !known {\n    let models = self.model_manager.get_models();\n    let fallback = models.iter().find(|m| m.is_downloaded)\n        .ok_or_else(|| anyhow::anyhow!(\"No downloaded model available\"))?;\n    self.transcription_manager.load_model(fallback.id.clone()).await?;\n} else {\n    self.transcription_manager.load_model(model_id.clone()).await?;\n}","handlingStrategy":"validation","validationCode":"let models = model_manager.get_models(); // current catalog snapshot\nlet valid = models.iter().any(|m| m.id == model_id);\nif !valid {\n    // pick a downloaded fallback or refresh settings before loading\n    let fallback = models.iter().find(|m| m.is_downloaded)\n        .ok_or_else(|| anyhow::anyhow!(\"No downloaded model available\"))?;\n    set_active_model(fallback.id.clone()).await?;\n    model_id = fallback.id.clone();\n}","typeGuard":"fn is_known_model_id(mm: &ModelManager, id: &str) -> bool {\n    mm.get_model_info(id).is_some()\n}","tryCatchPattern":"match transcription_manager.load_model(model_id.clone()).await {\n    Ok(()) => Ok(()),\n    Err(e) if e.to_string().starts_with(\"Model not found\") => {\n        // stale setting: re-resolve against the live catalog and retry once\n        let models = model_manager.get_models();\n        let fallback = models.iter().find(|m| m.is_downloaded)\n            .ok_or_else(|| anyhow::anyhow!(\"No downloaded model available\"))?;\n        transcription_manager.load_model(fallback.id.clone()).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Validate persisted model ids against get_available_models on every app start","After app updates that rename models, migrate old ids in settings","Always source ids from a freshly fetched catalog, never from cached frontend state"],"tags":["model-id","catalog","not-found","settings"],"backgroundTag":"unknown-model-id","analyzedSha":"98a4d80cce8ad41efec2a419b59d9e81229a35d7","analyzedAt":"2026-08-16T20:58:09.966Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}