{"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":2479,"sourceCode":"        } else {\n            // Update download status (marks predefined models as not downloaded)\n            self.update_download_status()?;\n            debug!(\"ModelManager: download status updated\");\n        }\n\n        // Emit event to notify UI\n        let _ = self.app_handle.emit(\"model-deleted\", model_id);\n\n        Ok(())\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":2461,"sourceCodeEnd":2497,"githubUrl":"https://github.com/cjpais/Handy/blob/98a4d80cce8ad41efec2a419b59d9e81229a35d7/src-tauri/src/managers/model.rs#L2461-L2497","documentation":"get_model_path found the model entry but is_downloaded is false — the model is known (e.g. in the catalog) but its file is not present locally. The subsequent checks (downloading, partial files) never run because this guard returns first.","triggerScenarios":"Recording started with a catalog model selected before it was downloaded; download interrupted leaving only a .partial; is_downloaded state stale after the file was deleted externally without a rescan.","commonSituations":"Fresh installs where settings default to a model the user never downloaded; manual deletion of model files from disk; failed downloads leaving the model marked not-downloaded.","solutions":["Download the model first (download_model) and wait for model-download-complete","Trigger a rescan/update_download_status if the file actually exists on disk but state is stale","In the UI, gate the record action on the selected model's is_downloaded flag"],"exampleFix":"// before\nlet path = manager.get_model_path(model_id)?;\n\n// after\nif let Some(info) = manager.get_model_info(model_id) {\n    if !info.is_downloaded {\n        anyhow::bail!(\"model {model_id} not downloaded — download it first\");\n    }\n}\nlet path = manager.get_model_path(model_id)?;","handlingStrategy":"validation","validationCode":"if let Some(info) = manager.get_model_info(model_id) {\n    if !info.is_downloaded {\n        anyhow::bail!(\"model {model_id} is not downloaded — start the download first\");\n    }\n    if info.is_downloading {\n        anyhow::bail!(\"model {model_id} is still downloading\");\n    }\n}\nlet path = manager.get_model_path(model_id)?;","typeGuard":null,"tryCatchPattern":"match manager.get_model_path(model_id) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"Model not available\") => {\n        // offer download or pick another model instead of failing the recording\n        anyhow::bail!(\"selected model needs downloading before recording\")\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Gate record actions on the selected model's is_downloaded flag in the UI","After a failed/interrupted download, rescan so is_downloaded matches disk","On fresh installs, default to a small model that downloads quickly or blocklist recording until one model exists"],"tags":["rust","model-manager","not-downloaded","state-mismatch"],"backgroundTag":"model-not-downloaded","analyzedSha":"98a4d80cce8ad41efec2a419b59d9e81229a35d7","analyzedAt":"2026-08-16T20:58:09.966Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}