{"record":{"id":"34f32ba071576f34","repo":"cjpais/Handy","slug":"complete-model-file-not-found-in-hf-cache-or-model","errorCode":null,"errorMessage":"Complete model file not found in HF cache or models dir: {}","messagePattern":"Complete model file not found in HF cache or models dir: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/model.rs","lineNumber":2508,"sourceCode":"        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.\n            let local_path = self.models_dir.join(&model_info.filename);\n            if local_path.exists() {\n                let partial_path = self\n                    .models_dir\n                    .join(format!(\"{}.partial\", &model_info.filename));\n                if partial_path.exists() {\n                    let _ = fs::remove_file(&partial_path);\n                }\n                return Ok(local_path);\n            }\n            return Err(anyhow::anyhow!(\n                \"Complete model file not found in HF cache or models dir: {}\",\n                model_id\n            ));\n        }\n\n        let model_path = self.models_dir.join(&model_info.filename);\n        let partial_path = self\n            .models_dir\n            .join(format!(\"{}.partial\", &model_info.filename));\n\n        if model_info.is_directory {\n            // For directory-based models, ensure the directory exists and is complete\n            if model_path.exists() && model_path.is_dir() && !partial_path.exists() {\n                Ok(model_path)\n            } else {\n                Err(anyhow::anyhow!(\n                    \"Complete model directory not found: {}\",\n                    model_id","sourceCodeStart":2490,"sourceCodeEnd":2526,"githubUrl":"https://github.com/cjpais/Handy/blob/98a4d80cce8ad41efec2a419b59d9e81229a35d7/src-tauri/src/managers/model.rs#L2490-L2526","documentation":"For a HuggingFace-sourced model, get_model_path first resolves the official HF cache via hf_cached_path(repo_id, revision, filename), then falls back to a manual drop-in under models_dir. This error means neither location holds the complete file even though the registry claims is_downloaded=true — the bookkeeping and the filesystem disagree. The stale .partial cleanup just above only runs when the local file does exist.","triggerScenarios":"The HF cache was evicted or cleared (huggingface-cli delete-cache, hf cache purge) while is_downloaded stayed true; HF_HOME/HF_ENDPOINT changed so hf_cached_path resolves elsewhere; models_dir moved or the drop-in file was deleted; the pinned revision snapshot no longer exists upstream.","commonSituations":"Users freeing disk space by deleting ~/.cache/huggingface; syncing settings to a new machine without syncing models; changing HF environment variables between runs; upstream repo deleting the pinned revision.","solutions":["Re-fetch the model: delete_model(model_id) then download_model(model_id)","Check hf_cached_path inputs — repo_id/revision/filename must match the actual cache layout (snapshots/<revision>/<filename>)","Restore or re-point the HF cache via HF_HOME to a location that still contains the snapshot","For manual installs, place a file named exactly model_info.filename in the configured models_dir and run rescan_local_models"],"exampleFix":"// before\nlet path = self.model_manager.get_model_path(model_id)?;\n\n// after — registry says downloaded but the bytes are gone: re-fetch\nlet path = match self.model_manager.get_model_path(model_id) {\n    Ok(p) => p,\n    Err(e) if self.model_manager.get_model_info(model_id)\n        .map(|i| i.is_downloaded).unwrap_or(false) => {\n        self.model_manager.delete_model(model_id)?;\n        self.download_and_wait(model_id).await?;\n        self.model_manager.get_model_path(model_id)?\n    }\n    Err(e) => return Err(e),\n};","handlingStrategy":"fallback","validationCode":"let info = model_manager.get_model_info(model_id)\n    .ok_or_else(|| anyhow::anyhow!(\"Model not found: {}\", model_id))?;\nif let ModelSource::HuggingFace { repo_id, revision } = &info.source {\n    let cached = hf_cached_path(repo_id, revision, &info.filename);\n    let local = model_manager.models_dir.join(&info.filename);\n    if cached.is_none() && !local.exists() {\n        // registry says downloaded but the file is gone — re-download now\n        model_manager.delete_model(model_id)?;\n        return re_download(model_id).await;\n    }\n}","typeGuard":"fn has_hf_model_bytes(\n    mm: &ModelManager,\n    repo_id: &str,\n    revision: &str,\n    filename: &str,\n) -> bool {\n    hf_cached_path(repo_id, revision, filename).is_some()\n        || mm.models_dir.join(filename).exists()\n}","tryCatchPattern":"match model_manager.get_model_path(model_id) {\n    Ok(p) => Ok(p),\n    Err(e) if e.to_string().contains(\"not found in HF cache\") => {\n        // bytes vanished despite is_downloaded=true: re-fetch as the fallback\n        model_manager.delete_model(model_id)?;\n        download_model_and_wait(model_id).await?;\n        model_manager.get_model_path(model_id)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Keep the HF cache location stable — set HF_HOME explicitly if the environment varies","After clearing the HF cache, also call delete_model so is_downloaded stays truthful","Name manual drop-in files exactly as the catalog's filename field"],"tags":["huggingface","hf-cache","file-not-found","model-download"],"backgroundTag":"huggingface-cache-miss","analyzedSha":"98a4d80cce8ad41efec2a419b59d9e81229a35d7","analyzedAt":"2026-08-16T20:58:09.966Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}