cjpais/Handy · error · anyhow::Error
Complete model file not found in HF cache or models dir: {}
Error message
Complete model file not found in HF cache or models dir: {} What it means
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.
Source
Thrown at src-tauri/src/managers/model.rs:2508
if let ModelSource::HuggingFace { repo_id, revision } = &model_info.source {
if let Some(path) = hf_cached_path(repo_id, revision, &model_info.filename) {
return Ok(path);
}
// Mirror-fallback download or manual drop-in in the models dir.
// The complete file only ever appears after verification, so a
// stale `.partial` alongside it is leftover noise, not a veto —
// clear it rather than declaring the model missing.
let local_path = self.models_dir.join(&model_info.filename);
if local_path.exists() {
let partial_path = self
.models_dir
.join(format!("{}.partial", &model_info.filename));
if partial_path.exists() {
let _ = fs::remove_file(&partial_path);
}
return Ok(local_path);
}
return Err(anyhow::anyhow!(
"Complete model file not found in HF cache or models dir: {}",
model_id
));
}
let model_path = self.models_dir.join(&model_info.filename);
let partial_path = self
.models_dir
.join(format!("{}.partial", &model_info.filename));
if model_info.is_directory {
// For directory-based models, ensure the directory exists and is complete
if model_path.exists() && model_path.is_dir() && !partial_path.exists() {
Ok(model_path)
} else {
Err(anyhow::anyhow!(
"Complete model directory not found: {}",
model_idView on GitHub (pinned to 98a4d80cce)
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
Example fix
// before
let path = self.model_manager.get_model_path(model_id)?;
// after — registry says downloaded but the bytes are gone: re-fetch
let path = match self.model_manager.get_model_path(model_id) {
Ok(p) => p,
Err(e) if self.model_manager.get_model_info(model_id)
.map(|i| i.is_downloaded).unwrap_or(false) => {
self.model_manager.delete_model(model_id)?;
self.download_and_wait(model_id).await?;
self.model_manager.get_model_path(model_id)?
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: fallback
Validate before calling
let info = model_manager.get_model_info(model_id)
.ok_or_else(|| anyhow::anyhow!("Model not found: {}", model_id))?;
if let ModelSource::HuggingFace { repo_id, revision } = &info.source {
let cached = hf_cached_path(repo_id, revision, &info.filename);
let local = model_manager.models_dir.join(&info.filename);
if cached.is_none() && !local.exists() {
// registry says downloaded but the file is gone — re-download now
model_manager.delete_model(model_id)?;
return re_download(model_id).await;
}
} Type guard
fn has_hf_model_bytes(
mm: &ModelManager,
repo_id: &str,
revision: &str,
filename: &str,
) -> bool {
hf_cached_path(repo_id, revision, filename).is_some()
|| mm.models_dir.join(filename).exists()
} Try / catch
match model_manager.get_model_path(model_id) {
Ok(p) => Ok(p),
Err(e) if e.to_string().contains("not found in HF cache") => {
// bytes vanished despite is_downloaded=true: re-fetch as the fallback
model_manager.delete_model(model_id)?;
download_model_and_wait(model_id).await?;
model_manager.get_model_path(model_id)
}
Err(e) => Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No model files found to delete
- Model is currently downloading: {}
- Complete model directory not found: {}
- Complete model file not found: {}
- Model not downloaded
AI-assisted analysis of cjpais/Handy@98a4d80cce (2026-08-16).
Data as JSON: /api/errors/34f32ba071576f34.
Report an issue: GitHub.