Hmbown/CodeWhale · error · anyhow::Error
installed package failed content digest validation: {err}
Error message
installed package failed content digest validation: {err} What it means
At the end of a skill-package install, the installer computes a content digest over the installed tree (compute_package_digest on final_path) so the .installed-from v2 marker can pin it. If digest computation itself fails (the wrapped {err}), the install is rolled back: final_path is removed, any pre-existing backup directory is renamed back into place, and this error is returned. It signals a filesystem-level failure while walking/reading the just-installed package, not a mismatch against an expected checksum.
Source
Thrown at crates/tui/src/skills/install.rs:377
if let Some(parent) = final_path.parent() {
fs::create_dir_all(parent).with_context(|| {
format!("failed to create skills directory {}", parent.display())
})?;
}
fs::rename(&staged.staged_path, &final_path).context("failed to install staged skill")?;
}
// Write the marker last so a partial install never leaves a stale
// .installed-from on disk. Prefer v2 with package content digest.
let spec = source_spec_string(&source);
let content_digest = match super::package_digest::compute_package_digest(&final_path) {
Ok(digest) => digest,
Err(err) => {
let _ = fs::remove_dir_all(&final_path);
if let Some(backup) = backup_path.take() {
let _ = fs::rename(&backup, &final_path);
}
return Err(anyhow::anyhow!(
"installed package failed content digest validation: {err}"
));
}
};
if let Err(err) = write_installed_from_v2(
&final_path,
&spec,
Some(&source_url),
&checksum,
&content_digest,
&staged.skill_name,
) {
let _ = fs::remove_dir_all(&final_path);
if let Some(backup) = backup_path.take() {
let _ = fs::rename(&backup, &final_path);
}
return Err(err);
}View on GitHub (pinned to 0c42157ee5)
Solutions
- Read the wrapped {err} — it names the exact file and I/O cause.
- Ensure no concurrent installs target the same skill (serialize installs or re-run the install once the other finishes).
- Check disk space and directory permissions on the skills root.
- On Windows, exclude the skills directory from antivirus scanning or pause watchers, then reinstall.
Defensive patterns
Strategy: retry
Try / catch
match install_skill(&source) {
Ok(_) => {}
Err(e) if e.to_string().contains("content digest validation") => {
// install was rolled back; inspect underlying cause, clear contention, retry once
log::warn!("skill install rolled back: {e:#}");
std::thread::sleep(std::time::Duration::from_secs(1));
install_skill(&source)?;
}
Err(e) => return Err(e),
} Prevention
- Serialize installs of the same skill — never run two installers against one skills directory at once.
- Keep the skills root writable and off paths scanned by antivirus/sync agents.
- Ensure adequate disk space before installing large skill packages.
When it happens
Trigger: compute_package_digest fails while walking final_path: a file becomes unreadable mid-walk (permissions changed), the tree is mutated concurrently by another install of the same skill, a path disappears between staging and digest, or an I/O error (full disk, failing drive, AV/lock interference) occurs.
Common situations: Two installs racing into the same skills directory; antivirus or file locks on Windows touching freshly written files; disk-full during a large package install; a watcher process pruning skill files as they land.
Related errors
- install source must not be empty
- github source must be 'github:owner/repo' (got {spec})
- only CodeWhale managed skills can be trusted
- SKILL.md is missing the closing '---' frontmatter fence
- invalid on-disk package directory for skill '{}'
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/68b92f87c0fbf0d4.
Report an issue: GitHub.