Hmbown/CodeWhale · error
owned skill path does not exist
Error message
owned skill path {} does not exist What it means
When the mutation requires the skill directory to already exist (require_existing), validate_owned_child checks it with checked_real_directory and fails if the path does not exist. Operations like update_skill need an on-disk skill package to modify; a missing directory means the skill was deleted or the name is wrong.
Solutions
- Re-run skill discovery to confirm the skill still exists on disk before updating; skip it if gone.
- Check the expected package directory name (on-disk casing) matches what is actually in the skills root.
- If the skill is legitimately missing, re-install it instead of updating.
Example fix
// before
for skill in stale_audit.skills {
update_skill(&ctx, &skill)?; // fails if deleted
}
// after
for skill in rediscover_skills(&ctx)? {
update_skill(&ctx, &skill)?;
} Defensive patterns
Strategy: validation
Validate before calling
fn skill_exists(skills_dir: &std::path::Path, package_name: &str) -> bool {
std::path::Path::new(skills_dir).join(package_name).is_dir()
} Try / catch
// skip or reinstall missing skills instead of failing the batch
match update_skill(&ctx, &skill) {
Err(e) if e.to_string().contains("does not exist") => {
eprintln!("skill {} vanished; reinstalling", skill.id.name);
install_skill(&ctx, &skill)?
}
other => other?,
} Prevention
- Re-discover skills immediately before updating instead of reusing old audit results.
- Match the on-disk package directory name exactly (casing included).
- Avoid external deletion of skill dirs (git clean / rm) while a mutation session is in flight.
When it happens
Trigger: Calling validate_owned_skill_path, update_skill (or install/import with require_existing=true) with a child path whose directory does not exist on disk — typically skills_dir.join(on_disk_package_name(skill.id)) after the package was removed, renamed, or the on-disk name differs from the audit record.
Common situations: The skill directory was deleted externally (git clean, manual rm) after auditing; the package folder name casing differs from the expected on-disk name; the audit is stale relative to disk state.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- audited owned root does not match mutation target
- audited skill root identity changed; refusing mutation
- fleet manager for run
- missing bounded fragment module
- missing TUI fragment module
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/739ac01646853496.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/skills/mutation.rs:304
let anchor = owned_anchor(ctx.workspace, ctx.home, target)?;
validate_owned_target_chain(anchor, &expected, true)?;
Ok(expected)
}
/// Validate a real direct child of an already validated owned skills root.
/// Returns false only when a missing child is permitted.
fn validate_owned_child(skills_dir: &Path, child: &Path, require_existing: bool) -> Result<bool> {
if child.parent() != Some(skills_dir) {
bail!(
"refusing to mutate path {} outside direct owned root {}",
child.display(),
skills_dir.display()
);
}
let exists = checked_real_directory(child)?;
if !exists {
if require_existing {
bail!("owned skill path {} does not exist", child.display());
}
return Ok(false);
}
let canonical_root = fs::canonicalize(skills_dir).with_context(|| {
format!(
"failed to resolve owned skill root {}",
skills_dir.display()
)
})?;
let canonical_child = fs::canonicalize(child)
.with_context(|| format!("failed to resolve owned skill path {}", child.display()))?;
if canonical_child.parent() != Some(canonical_root.as_path()) {
bail!(
"owned skill path {} escapes direct root {}",
child.display(),
skills_dir.display()
);View on GitHub (pinned to 73e0f67d83)