{"record":{"id":"27e6449f659e4c10","repo":"ultraworkers/claw-code","slug":"skill-source-not-found-e","errorCode":null,"errorMessage":"skill source '{}' not found: {e}","messagePattern":"skill source '(.+?)' not found: (.+?)","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"rust/crates/commands/src/lib.rs","lineNumber":3863,"sourceCode":"    }\n    if let Some(home) = env::var_os(\"HOME\") {\n        return Ok(PathBuf::from(home).join(\".claw\").join(\"skills\"));\n    }\n    Err(std::io::Error::new(\n        std::io::ErrorKind::NotFound,\n        \"unable to resolve a skills install root; set CLAW_CONFIG_HOME or HOME\",\n    ))\n}\n\nfn resolve_skill_install_source(source: &str, cwd: &Path) -> std::io::Result<SkillInstallSource> {\n    let candidate = PathBuf::from(source);\n    let source = if candidate.is_absolute() {\n        candidate\n    } else {\n        cwd.join(candidate)\n    };\n    let source = fs::canonicalize(&source).map_err(|e| {\n        std::io::Error::new(\n            e.kind(),\n            format!(\"skill source '{}' not found: {e}\", source.display()),\n        )\n    })?;\n\n    if source.is_dir() {\n        let prompt_path = source.join(\"SKILL.md\");\n        if !prompt_path.is_file() {\n            return Err(std::io::Error::new(\n                std::io::ErrorKind::InvalidInput,\n                format!(\n                    \"skill directory '{}' must contain SKILL.md\",\n                    source.display()\n                ),\n            ));\n        }\n        return Ok(SkillInstallSource::Directory {\n            root: source,","sourceCodeStart":3845,"sourceCodeEnd":3881,"githubUrl":"https://github.com/ultraworkers/claw-code/blob/08106b0c3771ef5b4a5aa176acccd460e88b7325/rust/crates/commands/src/lib.rs#L3845-L3881","documentation":"`resolve_skill_install_source` (commands/src/lib.rs:3863) builds a candidate from the `/skills install <source>` argument — absolute as-is, otherwise joined onto the handler's `cwd` (the process working directory, not your shell's notion of 'here') — then `fs::canonicalize` fails. The error re-wraps the OS error kind (NotFound, PermissionDenied, etc.) with the candidate path in the message.","triggerScenarios":"Passing a relative skill path to `/skills install` while the claw process runs with a different cwd; a typo in the path; the source being deleted between typing and executing; parent directory unreadable (canonicalize returns PermissionDenied).","commonSituations":"Installing from a path that is relative to the directory where claw was launched, not the directory the user thinks they are in; paths copied with a trailing `.` or wrong quoting; network-mounted homes where canonicalize can fail transiently.","solutions":["Pass an absolute path to `/skills install`.","Verify the path exists from the same cwd the claw process was started in (`pwd; ls <source>`).","Check the underlying kind in the message — PermissionDenied means a parent dir traversal problem, not a typo."],"exampleFix":"# before\n/skills install my-skill          # skill source 'my-skill' not found ...\n\n# after\n/skills install /home/me/skills/my-skill","handlingStrategy":"validation","validationCode":"// mirror resolve_skill_install_source's resolution before calling install\nlet candidate = Path::new(source);\nlet candidate = if candidate.is_absolute() { candidate.to_path_buf() } else { cwd.join(candidate) };\nif !candidate.exists() { /* fix the path, don't call install */ }","typeGuard":null,"tryCatchPattern":"if let Err(e) = install_skill(source, cwd) {\n    if e.to_string().contains(\"skill source\") && e.to_string().contains(\"not found\") {\n        // re-resolve as absolute path and retry\n    }\n}","preventionTips":["Prefer absolute paths for /skills install","Relative paths resolve against the claw process cwd — verify with pwd","Canonicalize or at least `ls` the path from the same cwd first"],"tags":["skills","install","path","not-found"],"backgroundTag":"file-not-found","analyzedSha":"08106b0c3771ef5b4a5aa176acccd460e88b7325","analyzedAt":"2026-08-18T00:29:38.590Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}