{"record":{"id":"1619e1410c6600a4","repo":"cjpais/Handy","slug":"error-msg-dynamic-model-loading-failure-message","errorCode":null,"errorMessage":"error_msg (dynamic: model loading failure message)","messagePattern":"error_msg \\(dynamic: model loading failure message\\)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/transcription.rs","lineNumber":514,"sourceCode":"                model_name: None,\n                error: None,\n            },\n        );\n\n        let model_info = match self.model_manager.get_model_info(model_id) {\n            Some(model_info) => model_info,\n            None => {\n                let error_msg = format!(\"Model not found: {}\", model_id);\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: None,\n                        error: Some(error_msg.clone()),\n                    },\n                );\n                return Err(anyhow::anyhow!(error_msg));\n            }\n        };\n\n        // Every failure after loading starts must emit a terminal event so the\n        // frontend can never remain in its loading state.\n        let emit_loading_failed = |error_msg: &str| {\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        };\n\n        if !model_info.is_downloaded {","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/cjpais/Handy/blob/ba10ce1943ef34e93c09494027fc0b9ced2e8a44/src-tauri/src/managers/transcription.rs#L496-L532","documentation":"In TranscriptionManager::load_model_with_device, when get_model_info(model_id) returns None the manager formats a dynamic \"Model not found: <id>\" message, emits a model-state-changed 'loading_failed' event so the frontend leaves its loading state, and returns this error via anyhow. It means the requested model_id does not correspond to any model known to the ModelManager.","triggerScenarios":"Calling load_model(model_id) or load_model_with_device(model_id, device) with an id that has no entry in the model registry: a typo'd/hardcoded id, an id from an older app version whose model list changed, a stale id persisted in settings or passed from the frontend before the model catalog initialized.","commonSituations":"Settings file or persisted store still references a model id removed/renamed after an app update; frontend sends an id from an outdated bindings/types list; third-party scripts invoking remote-control flags with an invalid model id; plugin/custom code constructing ids by hand instead of enumerating available models.","solutions":["Fix the model_id string: enumerate valid ids via the model manager's list/info API (or the model-selector UI) and use one of those exact ids.","Reset or edit the persisted settings so they reference an existing model id, then reload.","If the id comes from stored state after an app update, re-select the model in the UI to refresh the stored id.","Wrap the load call and listen for the 'model-state-changed' loading_failed event in the frontend to recover UI state (the event is always emitted before this error propagates)."],"exampleFix":"// before\ntranscription.load_model(\"whisper-base-q5\")?; // typo, no such id\n// after\nlet id = model_manager.list_models()\n    .into_iter()\n    .find(|m| m.name.contains(\"Base\"))\n    .map(|m| m.id)\n    .ok_or_else(|| anyhow::anyhow!(\"no suitable model installed\"))?;\ntranscription.load_model(&id)?;","handlingStrategy":"validation","validationCode":"// Rust: verify the id exists before loading\nif model_manager.get_model_info(model_id).is_none() {\n    return Err(anyhow::anyhow!(\"unknown model id: {}\", model_id));\n}\ntranscription.load_model(model_id)?;\n\n// Frontend: check against the catalog first\nconst known = models.some(m => m.id === modelId);\nif (!known) throw new Error(`unknown model id: ${modelId}`);","typeGuard":"// Frontend narrowing: only pass ids from the typed catalog\nfunction isKnownModelId(\n  id: string,\n  models: { id: string }[],\n): id is string {\n  return models.some((m) => m.id === id);\n}","tryCatchPattern":"// Rust\nif let Err(e) = transcription.load_model(model_id) {\n    log::error!(\"load failed: {e}\");\n    // frontend also receives model-state-changed 'loading_failed' here\n    fallback_to_default_model()?;\n}\n\n// Frontend\nlisten('model-state-changed', (ev) => {\n  if (ev.payload.event_type === 'loading_failed') resetLoadingUi(ev.payload.error);\n});","preventionTips":["Never hardcode model id strings; always obtain ids from the model list/info API or generated bindings.","After app updates, re-validate any model id persisted in settings against the current catalog before loading.","Normalize/trim user-supplied ids and compare case-sensitively against the registry.","Subscribe to the 'model-state-changed' loading_failed event so the UI never gets stuck when this error fires."],"tags":["model-management","invalid-identifier","lookup-failed","tauri"],"backgroundTag":"record-not-found","analyzedSha":"ba10ce1943ef34e93c09494027fc0b9ced2e8a44","analyzedAt":"2026-09-17T15:09:05.215Z","contentChangedAt":"2026-09-17T15:09:05.215Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}