cjpais/Handy · error · anyhow::Error
Model directory is incomplete
Error message
Model directory is incomplete: {} What it means
Thrown by ModelManager::get_model_path when a directory-based model (is_directory == true, e.g. multi-file model bundles in the models dir) exists at its expected path, but a sibling `<filename>.partial` file is still present. The `.partial` marker is written during downloads and only removed after the download is fully verified, so its presence means the directory on disk is not a complete, verified model. The manager refuses to hand back a path that could point at half-written model data.
Solutions
- Delete the stale `<model_filename>.partial` file inside the models directory, then retry (if the model directory itself is complete, this is enough).
- If the directory contents are also suspect, delete the model directory entirely and re-download it via the app's model manager.
- Check the download is not actually still in progress (get_model_info / is_downloading) before touching files.
- Upgrade the app: newer code treats a complete model alongside a `.partial` as leftover noise and removes it automatically rather than erroring.
Example fix
// before: stale marker blocks a good directory ls models_dir # my-model-dir/ my-model-dir.partial rm models_dir/my-model-dir.partial // after: get_model_path returns the directory
Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn model_dir_complete(models_dir: &Path, filename: &str) -> bool {
let dir = models_dir.join(filename);
dir.is_dir() && !models_dir.join(format!("{}.partial", filename)).exists()
}
// call before get_model_path/load_model; if false, clean up or re-download Type guard
fn is_complete_model_dir(p: &Path) -> bool {
p.is_dir() && !p.with_file_name(format!("{}.partial", p.file_name().map(|s| s.to_string_lossy().to_string()).unwrap_or_default())).exists()
} Try / catch
match manager.get_model_path(id) {
Ok(p) => p,
Err(e) if e.to_string().contains("incomplete") => {
// remove stale <file>.partial, then retry once
let partial = models_dir.join(format!("{}.partial", filename));
let _ = std::fs::remove_file(&partial);
manager.get_model_path(id).context("model still incomplete after cleanup")?
}
Err(e) => return Err(e),
} Prevention
- Never kill the app or the machine during a model download; use cancel_download to stop cleanly.
- After an app crash, sweep the models dir for *.partial files before loading models.
- Exclude the models dir from cloud-sync/backup restore tools that can resurrect partial files.
- Keep the app updated: newer versions auto-clear stale .partial markers instead of erroring.
When it happens
Trigger: Calling get_model_path(model_id) (directly or via load_model/load_model_with_device) for a directory-based model when: (1) a previous download of that model was interrupted (crash, kill, power loss) after the directory was created but before the `.partial` file was cleaned up; (2) a download is still running in another thread while is_downloading was somehow false; (3) a `.partial` file was left behind by an older app version with a different download scheme.
Common situations: User force-quits the app mid-download and later restarts; system crash or disk-full during a model download; manually copying a model folder into models/ while leaving a stale `.partial` beside it; restoring a partially-synced models directory from a backup or cloud-sync tool.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Model file is incomplete
- Complete model file not found
- error_msg (dynamic: model loading failure message)
- Failed to initialize model manager
- Failed to initialize store
AI-assisted analysis of cjpais/Handy@ba10ce1943 (2026-09-17).
Data as JSON: /api/errors/895e549e032c2ccc.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/managers/model.rs:2618
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 {
if !model_path.exists() || !model_path.is_dir() {
self.mark_model_unavailable(model_id);
return Err(anyhow::anyhow!(
"Complete model directory not found: {}",
model_id
));
}
if partial_path.exists() {
return Err(anyhow::anyhow!(
"Model directory is incomplete: {}",
model_id
));
}
Ok(model_path)
} else {
if !model_path.exists() {
self.mark_model_unavailable(model_id);
return Err(anyhow::anyhow!(
"Complete model file not found: {}",
model_id
));
}
if partial_path.exists() {
return Err(anyhow::anyhow!("Model file is incomplete: {}", model_id));
}
Ok(model_path)
}View on GitHub (pinned to ba10ce1943)