{"record":{"id":"895e549e032c2ccc","repo":"cjpais/Handy","slug":"model-directory-is-incomplete","errorCode":null,"errorMessage":"Model directory is incomplete: {}","messagePattern":"Model directory is incomplete: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/model.rs","lineNumber":2618,"sourceCode":"                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            if !model_path.exists() || !model_path.is_dir() {\n                self.mark_model_unavailable(model_id);\n                return Err(anyhow::anyhow!(\n                    \"Complete model directory not found: {}\",\n                    model_id\n                ));\n            }\n            if partial_path.exists() {\n                return Err(anyhow::anyhow!(\n                    \"Model directory is incomplete: {}\",\n                    model_id\n                ));\n            }\n            Ok(model_path)\n        } else {\n            if !model_path.exists() {\n                self.mark_model_unavailable(model_id);\n                return Err(anyhow::anyhow!(\n                    \"Complete model file not found: {}\",\n                    model_id\n                ));\n            }\n            if partial_path.exists() {\n                return Err(anyhow::anyhow!(\"Model file is incomplete: {}\", model_id));\n            }\n            Ok(model_path)\n        }","sourceCodeStart":2600,"sourceCodeEnd":2636,"githubUrl":"https://github.com/cjpais/Handy/blob/ba10ce1943ef34e93c09494027fc0b9ced2e8a44/src-tauri/src/managers/model.rs#L2600-L2636","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: stale marker blocks a good directory\nls models_dir\n# my-model-dir/  my-model-dir.partial\nrm models_dir/my-model-dir.partial\n// after: get_model_path returns the directory","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn model_dir_complete(models_dir: &Path, filename: &str) -> bool {\n    let dir = models_dir.join(filename);\n    dir.is_dir() && !models_dir.join(format!(\"{}.partial\", filename)).exists()\n}\n// call before get_model_path/load_model; if false, clean up or re-download","typeGuard":"fn is_complete_model_dir(p: &Path) -> bool {\n    p.is_dir() && !p.with_file_name(format!(\"{}.partial\", p.file_name().map(|s| s.to_string_lossy().to_string()).unwrap_or_default())).exists()\n}","tryCatchPattern":"match manager.get_model_path(id) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"incomplete\") => {\n        // remove stale <file>.partial, then retry once\n        let partial = models_dir.join(format!(\"{}.partial\", filename));\n        let _ = std::fs::remove_file(&partial);\n        manager.get_model_path(id).context(\"model still incomplete after cleanup\")?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["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."],"tags":["model-management","download-incomplete","filesystem","stale-state"],"backgroundTag":"file-already-exists","analyzedSha":"ba10ce1943ef34e93c09494027fc0b9ced2e8a44","analyzedAt":"2026-09-17T15:09:05.215Z","contentChangedAt":"2026-09-17T15:09:05.215Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}