Hmbown/CodeWhale · error
refusing to mutate through non-directory CodeWhale skills pa
Error message
refusing to mutate through non-directory CodeWhale skills path component {} What it means
checked_real_directory found that a component of the owned skills path exists but is not a directory (a file, or another non-directory entry) and is not a symlink. Writes cannot proceed because the expected directory component is occupied by a non-directory; the offending path component is the input at fault. Generic validation guard used by validate_owned_target_chain, create_owned_directory, prepare_owned_target, and validate_owned_child.
Source
Thrown at crates/tui/src/skills/mutation.rs:154
match target {
SkillTargetScope::Project => Ok(workspace),
SkillTargetScope::Global => home.context("global skill mutations require a home directory"),
}
}
/// Return whether `path` is an existing real directory, rejecting links and
/// non-directory components. `symlink_metadata` is intentional: following a
/// link before checking it would turn a lexical CodeWhale-owned root into an
/// attacker-selected write target.
fn checked_real_directory(path: &Path) -> Result<bool> {
match fs::symlink_metadata(path) {
Ok(meta) if meta.file_type().is_symlink() => {
bail!(
"refusing to mutate symlinked CodeWhale skills path component {}",
path.display()
)
}
Ok(meta) if !meta.is_dir() => bail!(
"refusing to mutate through non-directory CodeWhale skills path component {}",
path.display()
),
Ok(_) => Ok(true),
Err(err) if err.kind() == ErrorKind::NotFound => Ok(false),
Err(err) => Err(err).with_context(|| format!("failed to inspect {}", path.display())),
}
}
/// Validate the complete owned-root chain without following a symlink in the
/// workspace/home anchor, `.codewhale`, or `skills` component.
fn validate_owned_target_chain(
anchor: &Path,
skills_dir: &Path,
require_existing: bool,
) -> Result<()> {
let expected = anchor.join(".codewhale").join("skills");
if skills_dir != expected {View on GitHub (pinned to 0c42157ee5)
Solutions
- Inspect the reported path component and remove or rename the file occupying it
- Let CodeWhale recreate the .codewhale/skills directory structure after clearing the obstruction
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/tui/src/skills/mutation.rs:154 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/9504e7bdb693463d.
Report an issue: GitHub.