{"record":{"id":"6e5ac8bb1313b9c0","repo":"Hmbown/CodeWhale","slug":"refusing-to-mutate-non-canonical-codewhale-skills","errorCode":null,"errorMessage":"refusing to mutate non-canonical CodeWhale skills root {}","messagePattern":"refusing to mutate non-canonical CodeWhale skills root (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/mutation.rs","lineNumber":173,"sourceCode":"            \"refusing to mutate through non-directory CodeWhale skills path component {}\",\n            path.display()\n        ),\n        Ok(_) => Ok(true),\n        Err(err) if err.kind() == ErrorKind::NotFound => Ok(false),\n        Err(err) => Err(err).with_context(|| format!(\"failed to inspect {}\", path.display())),\n    }\n}\n\n/// Validate the complete owned-root chain without following a symlink in the\n/// workspace/home anchor, `.codewhale`, or `skills` component.\nfn validate_owned_target_chain(\n    anchor: &Path,\n    skills_dir: &Path,\n    require_existing: bool,\n) -> Result<()> {\n    let expected = anchor.join(\".codewhale\").join(\"skills\");\n    if skills_dir != expected {\n        bail!(\n            \"refusing to mutate non-canonical CodeWhale skills root {}\",\n            skills_dir.display()\n        );\n    }\n\n    let anchor_exists = checked_real_directory(anchor)?;\n    if !anchor_exists {\n        if require_existing {\n            bail!(\"owned skill anchor {} does not exist\", anchor.display());\n        }\n        return Ok(());\n    }\n\n    let codewhale_dir = anchor.join(\".codewhale\");\n    let codewhale_exists = checked_real_directory(&codewhale_dir)?;\n    if !codewhale_exists {\n        if require_existing {\n            bail!(","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/skills/mutation.rs#L155-L191","documentation":"validate_owned_target_chain compares the skills_dir under mutation against the canonical expected chain <anchor>/.codewhale/skills and refuses any other path. A non-canonical root means a caller (or a stale/rewritten descriptor) is asking to mutate a skills directory that is not the real CodeWhale-owned location for the given workspace/home anchor. The mismatched skills_dir path is the input at fault.","triggerScenarios":"Thrown at crates/tui/src/skills/mutation.rs:173 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use the canonical .codewhale/skills path under the workspace or home anchor","Check for misconfigured skills_dir overrides pointing outside the anchor","Refresh the skill root descriptor so it reflects the current owned root"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}