{"record":{"id":"7c73d6e9bffaafe1","repo":"cjpais/Handy","slug":"failed-to-extract-archive","errorCode":null,"errorMessage":"Failed to extract archive: {}","messagePattern":"Failed to extract archive: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/model.rs","lineNumber":2330,"sourceCode":"                let error_msg = format!(\"Failed to extract archive: {}\", e);\n                // Clean up failed extraction\n                let _ = fs::remove_dir_all(&temp_extract_dir);\n                // Delete the corrupt partial file so the next download attempt starts fresh\n                // instead of resuming from a broken archive (issue #858).\n                let _ = fs::remove_file(&partial_path);\n                // Remove from extracting set\n                {\n                    let mut extracting = self.extracting_models.lock().unwrap();\n                    extracting.remove(model_id);\n                }\n                let _ = self.app_handle.emit(\n                    \"model-extraction-failed\",\n                    &serde_json::json!({\n                        \"model_id\": model_id,\n                        \"error\": error_msg\n                    }),\n                );\n                anyhow::anyhow!(error_msg)\n            })?;\n\n            // Find the actual extracted directory (archive might have a nested structure)\n            let extracted_dirs: Vec<_> = fs::read_dir(&temp_extract_dir)?\n                .filter_map(|entry| entry.ok())\n                .filter(|entry| entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false))\n                .collect();\n\n            if extracted_dirs.len() == 1 {\n                // Single directory extracted, move it to the final location\n                let source_dir = extracted_dirs[0].path();\n                if final_model_dir.exists() {\n                    fs::remove_dir_all(&final_model_dir)?;\n                }\n                fs::rename(&source_dir, &final_model_dir)?;\n                // Clean up temp directory\n                let _ = fs::remove_dir_all(&temp_extract_dir);\n            } else {","sourceCodeStart":2312,"sourceCodeEnd":2348,"githubUrl":"https://github.com/cjpais/Handy/blob/ba10ce1943ef34e93c09494027fc0b9ced2e8a44/src-tauri/src/managers/model.rs#L2312-L2348","documentation":"Extraction of a downloaded archive-based (directory) model failed: the inner extraction block captures the error as error_msg, emits the model-extraction-failed event with the model_id and error, removes the model from the extracting set, and rethrows via `anyhow::anyhow!(error_msg)`. Extraction runs into a temp dir which is then moved to the final model dir, so failures are typically a corrupt archive or filesystem problems.","triggerScenarios":"Truncated/corrupted archive from an interrupted or bit-rotted download; unsupported compression method inside the zip; disk full during extraction (archive + extracted copy coexist); temp dir or destination permissions; antivirus/locked files on Windows mid-extract.","commonSituations":"Download 'completed' but the file was cut short by a stall; extracting multi-GB models on a nearly-full disk; EDR software quarantining or locking extracted binaries; extracting into a read-only or roaming-profile directory.","solutions":["Delete the model entry and its leftover files, then re-download — a fresh archive fixes corruption","Free disk space: budget for archive plus extracted content simultaneously","Check temp dir and models dir permissions; on Windows, add an antivirus exclusion for the models dir","Listen for the model-extraction-failed event in the UI to surface the detailed error to the user"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// require room for archive + extracted copy before starting\nfn disk_space_sufficient(models_dir: &Path, model_bytes: u64) -> bool {\n    // rough rule: 2.2x the archive size covers download + extract + move\n    fs2::available_space(models_dir).map(|f| f > model_bytes * 2).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = install.extract() {\n    // error_msg already emitted as model-extraction-failed; a clean re-download is the fix\n    let _ = manager.delete_model(model_id);\n    manager.download_model(model_id).await?; // retry once with a fresh archive\n}","preventionTips":["Verify the archive checksum (sha256 already known for Url models) before extracting","Extract to the same filesystem as the final dir so the move can't fail across devices","Subscribe to the model-extraction-failed event in the UI to show the detailed cause"],"tags":["rust","archive","zip","extraction","model","disk-space"],"backgroundTag":"archive-extraction-failed","analyzedSha":"ba10ce1943ef34e93c09494027fc0b9ced2e8a44","analyzedAt":"2026-08-17T10:29:55.597Z","contentChangedAt":"2026-08-17T10:29:55.597Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}