Hmbown/CodeWhale · error · anyhow::Error

refusing to mutate non-owned root {}

Error message

refusing to mutate non-owned root {}

What it means

target_scope_for_root only permits roots marked writable-owned (CodeWhaleProject or CodeWhaleGlobal kinds); this bail fires for any other root descriptor passed to a mutation. It means the operation was aimed at an external/harness-managed skills directory (e.g. a compatible external root), which CodeWhale deliberately never writes to. The non-owned root path is the input at fault.

Source

Thrown at crates/tui/src/skills/mutation.rs:264

    if !checked_real_directory(anchor)? {
        bail!("owned skill anchor {} does not exist", anchor.display());
    }

    let codewhale_dir = anchor.join(".codewhale");
    if !checked_real_directory(&codewhale_dir)? {
        create_owned_directory(&codewhale_dir)?;
    }
    validate_owned_target_chain(anchor, &skills_dir, false)?;
    if !checked_real_directory(&skills_dir)? {
        create_owned_directory(&skills_dir)?;
    }
    validate_owned_target_chain(anchor, &skills_dir, true)?;
    Ok(skills_dir)
}

fn target_scope_for_root(root: &SkillRootDescriptor) -> Result<SkillTargetScope> {
    if !root.is_writable_owned() {
        bail!("refusing to mutate non-owned root {}", root.path.display());
    }
    match root.kind {
        SkillRootKind::CodeWhaleProject => Ok(SkillTargetScope::Project),
        SkillRootKind::CodeWhaleGlobal => Ok(SkillTargetScope::Global),
        _ => bail!("refusing to mutate non-owned root {}", root.path.display()),
    }
}

fn validate_owned_root_descriptor(
    ctx: &MutationContext<'_>,
    root: &SkillRootDescriptor,
) -> Result<PathBuf> {
    let target = target_scope_for_root(root)?;
    let expected = resolve_owned_target(ctx.workspace, ctx.home, target)?;
    if root.path != expected {
        bail!(
            "audited owned root {} does not match mutation target {}",
            root.path.display(),

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Target a CodeWhale-owned project or global skills root instead of the external one
  2. Import the skill into an owned root first, then mutate it there
  3. Point the command at the correct root descriptor
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/tui/src/skills/mutation.rs:264 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/806dedc97c957634. Report an issue: GitHub.