{"record":{"id":"1854ef27b9b538f2","repo":"Hmbown/CodeWhale","slug":"refusing-to-mutate-path-outside-direct-owned-ro","errorCode":null,"errorMessage":"refusing to mutate path {} outside direct owned root {}","messagePattern":"refusing to mutate path (.+?) outside direct owned root (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/mutation.rs","lineNumber":295,"sourceCode":"    let target = target_scope_for_root(root)?;\n    let expected = resolve_owned_target(ctx.workspace, ctx.home, target)?;\n    if root.path != expected {\n        bail!(\n            \"audited owned root {} does not match mutation target {}\",\n            root.path.display(),\n            expected.display()\n        );\n    }\n    let anchor = owned_anchor(ctx.workspace, ctx.home, target)?;\n    validate_owned_target_chain(anchor, &expected, true)?;\n    Ok(expected)\n}\n\n/// Validate a real direct child of an already validated owned skills root.\n/// Returns false only when a missing child is permitted.\nfn validate_owned_child(skills_dir: &Path, child: &Path, require_existing: bool) -> Result<bool> {\n    if child.parent() != Some(skills_dir) {\n        bail!(\n            \"refusing to mutate path {} outside direct owned root {}\",\n            child.display(),\n            skills_dir.display()\n        );\n    }\n    let exists = checked_real_directory(child)?;\n    if !exists {\n        if require_existing {\n            bail!(\"owned skill path {} does not exist\", child.display());\n        }\n        return Ok(false);\n    }\n\n    let canonical_root = fs::canonicalize(skills_dir).with_context(|| {\n        format!(\n            \"failed to resolve owned skill root {}\",\n            skills_dir.display()\n        )","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/skills/mutation.rs#L277-L313","documentation":"validate_owned_child requires the target path to be a direct child of the validated owned skills root (child.parent() == skills_dir). This bail fires when the requested mutation path is nested deeper, sits in another directory, or is otherwise outside the owned root — a traversal/containment rejection. The out-of-root child path is the input at fault.","triggerScenarios":"Thrown at crates/tui/src/skills/mutation.rs:295 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Pass the skill package directory directly under the owned skills root","Check for typos or extra path segments in the target path","Operate via skill name/id rather than a hand-built path so the correct child is derived"],"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"}