{"record":{"id":"420357d55ccb4dfe","repo":"cjpais/Handy","slug":"model-not-available","errorCode":null,"errorMessage":"Model not available: {}","messagePattern":"Model not available: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/model.rs","lineNumber":2568,"sourceCode":"\n        if removed {\n            info!(\"Removing vanished discovered model '{}'\", model_id);\n        } else {\n            info!(\"Marking model '{}' as unavailable on disk\", model_id);\n        }\n        // Keep the persisted preference here: an already-loaded engine may\n        // still be usable, and re-downloading this model should restore it.\n        // Startup and explicit Rescan perform the broader selection cleanup.\n        let _ = self.app_handle.emit(\"models-updated\", ());\n    }\n\n    pub fn get_model_path(&self, model_id: &str) -> Result<PathBuf> {\n        let model_info = self\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            return Err(anyhow::anyhow!(\"Model not available: {}\", model_id));\n        }\n\n        // Ensure we don't return partial files/directories\n        if model_info.is_downloading {\n            return Err(anyhow::anyhow!(\n                \"Model is currently downloading: {}\",\n                model_id\n            ));\n        }\n\n        if let ModelSource::HuggingFace { repo_id, revision } = &model_info.source {\n            if let Some(path) = hf_cached_path(repo_id, revision, &model_info.filename) {\n                return Ok(path);\n            }\n            // Mirror-fallback download or manual drop-in in the models dir.\n            // The complete file only ever appears after verification, so a\n            // stale `.partial` alongside it is leftover noise, not a veto —\n            // clear it rather than declaring the model missing.","sourceCodeStart":2550,"sourceCodeEnd":2586,"githubUrl":"https://github.com/cjpais/Handy/blob/ba10ce1943ef34e93c09494027fc0b9ced2e8a44/src-tauri/src/managers/model.rs#L2550-L2586","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","solutions":["Trigger downloadModel and wait for the model-download-complete event before enabling recording","Restrict the model selector in settings to entries with is_downloaded true","If it just completed, refresh model status — the flag updates via update_download_status"],"exampleFix":"// before (TS) — start recording regardless of model state\nawait startRecording();\n\n// after — gate recording on the selected model being ready\nconst info = await commands.getModelInfo(selectedModelId);\nif (info.status === \"ok\" && !info.data.is_downloaded) {\n  await commands.downloadModel(selectedModelId);\n  // wait for the model-download-complete event before proceeding\n}\nawait startRecording();","handlingStrategy":"validation","validationCode":"// gate on download state before resolving the path\nlet info = manager.get_model_info(model_id)\n    .ok_or_else(|| anyhow::anyhow!(\"Model not found: {model_id}\"))?;\nif !info.is_downloaded {\n    manager.download_model(model_id).await?; // caller waits for model-download-complete\n}","typeGuard":null,"tryCatchPattern":"match manager.get_model_path(id) {\n    Err(e) if e.to_string().contains(\"Model not available\") => {\n        // trigger download and surface 'model not ready' to the user — do not transcribe\n    }\n    other => other,\n}","preventionTips":["Only allow selecting downloaded models as the active transcription model","Wait for the model-download-complete event after triggering downloads before enabling recording"],"tags":["rust","model","download-state","transcription"],"backgroundTag":"resource-not-ready","analyzedSha":"ba10ce1943ef34e93c09494027fc0b9ced2e8a44","analyzedAt":"2026-08-17T10:29:55.597Z","contentChangedAt":"2026-08-17T10:29:55.597Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}