{"record":{"id":"edd9affd70595bb4","repo":"Hmbown/CodeWhale","slug":"failed-to-create-owned-skill-directory","errorCode":null,"errorMessage":"failed to create owned skill directory {}","messagePattern":"failed to create owned skill directory (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/mutation.rs","lineNumber":234,"sourceCode":"        bail!(\n            \"owned skill root {} escapes anchor {}\",\n            skills_dir.display(),\n            anchor.display()\n        );\n    }\n    Ok(())\n}\n\nfn create_owned_directory(path: &Path) -> Result<()> {\n    match fs::create_dir(path) {\n        Ok(()) => {}\n        Err(err) if err.kind() == ErrorKind::AlreadyExists => {}\n        Err(err) => {\n            return Err(err).with_context(|| format!(\"failed to create {}\", path.display()));\n        }\n    }\n    if !checked_real_directory(path)? {\n        bail!(\"failed to create owned skill directory {}\", path.display());\n    }\n    Ok(())\n}\n\nfn prepare_owned_target(\n    workspace: &Path,\n    home: Option<&Path>,\n    target: SkillTargetScope,\n) -> Result<PathBuf> {\n    let skills_dir = resolve_owned_target(workspace, home, target)?;\n    let anchor = owned_anchor(workspace, home, target)?;\n    if !checked_real_directory(anchor)? {\n        bail!(\"owned skill anchor {} does not exist\", anchor.display());\n    }\n\n    let codewhale_dir = anchor.join(\".codewhale\");\n    if !checked_real_directory(&codewhale_dir)? {\n        create_owned_directory(&codewhale_dir)?;","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/skills/mutation.rs#L216-L252","documentation":"create_owned_directory called fs::create_dir and then re-validated with checked_real_directory; the latter returned false, meaning that after the create (or AlreadyExists tolerance) the path is still not a real, non-symlink directory. Typically a race replaced the path with a symlink/file between the create and the check, so the owned directory could not be established. The contested path is the input at fault.","triggerScenarios":"Thrown at crates/tui/src/skills/mutation.rs:234 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Re-run the operation; a concurrent process may have swapped the path","Inspect the path for a symlink or file that replaced the directory and remove it","Ensure no other tool is creating symlinks inside .codewhale"],"exampleFix":null,"handlingStrategy":"fallback","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-14T05:17:10.506Z"}