{"record":{"id":"2a556133ef110693","repo":"zeroclaw-labs/zeroclaw","slug":"skill-skill-not-found-in-url-no-skills-d","errorCode":null,"errorMessage":"skill '{$skill}' not found in {$url}: no skills/ directory, or it is empty","messagePattern":"skill '(.+?)' not found in (.+?): no skills/ directory, or it is empty","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/skills/mod.rs","lineNumber":2398,"sourceCode":"        )\n    })?;\n\n    (|| {\n        // Establish the catalog trust boundary before looking up a selected\n        // name or enumerating available names. A catalog controls `skills/`,\n        // so following it before this check could inspect an arbitrary host\n        // directory even when the requested skill does not exist.\n        let clone_root = clone_dir.canonicalize().with_context(|| {\n            format!(\n                \"failed to canonicalize catalog clone {}\",\n                clone_dir.display()\n            )\n        })?;\n        let skills_dir = clone_dir.join(\"skills\");\n        let skills_meta = match std::fs::symlink_metadata(&skills_dir) {\n            Ok(metadata) => metadata,\n            Err(err) if err.kind() == std::io::ErrorKind::NotFound => {\n                anyhow::bail!(crate::i18n::get_required_cli_string_with_args(\n                    \"cli-skills-install-skill-not-in-catalog-empty\",\n                    &[(\"skill\", skill_name), (\"url\", url)]\n                ));\n            }\n            Err(err) => {\n                return Err(err).with_context(|| {\n                    format!(\n                        \"failed to read metadata for catalog skills root {}\",\n                        skills_dir.display()\n                    )\n                });\n            }\n        };\n        if skills_meta.file_type().is_symlink() {\n            anyhow::bail!(crate::i18n::get_required_cli_string_with_args(\n                \"cli-skills-install-catalog-root-symlink\",\n                &[(\"url\", url)]\n            ));","sourceCodeStart":2380,"sourceCodeEnd":2416,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/skills/mod.rs#L2380-L2416","documentation":"After cloning the catalog repo into a temp dir, symlink_metadata on <clone>/skills returned NotFound: the catalog has no skills/ directory at its root. The catalog layout contract is <repo>/skills/<skill-name>/, so a repo without a root skills/ directory cannot serve as a skills catalog.","triggerScenarios":"URL points at a repo that stores skills at the repository root or under a different folder (skill/, packages/); the URL points at an ordinary project repo rather than a skills catalog.","commonSituations":"Pointing the catalog install at a normal project repository; a catalog repo that changed its layout between versions.","solutions":["Check the repo: it must contain a skills/ directory at the root with one directory per skill","If the skills live elsewhere, clone the repo yourself and install the wanted folder via the local-source installer","Use a catalog repo that follows the <repo>/skills/<name>/ layout"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Optional pre-flight: confirm the repo looks like a catalog before offering it\nlet out = std::process::Command::new(\"git\")\n    .args([\"ls-remote\", url])\n    .output()?;\nif !out.status.success() {\n    anyhow::bail!(\"catalog repo unreachable: {url}\");\n}\n// layout itself can only be verified after clone — handle at runtime","typeGuard":null,"tryCatchPattern":"match install_git_catalog_skill_source(url, skill, &skills_path, false, &ws) {\n    Err(e) if e.to_string().contains(\"no skills/ directory, or it is empty\")\n            && !e.to_string().contains(\"Available skills\") => {\n        // catalog lacks the <repo>/skills/ layout: use a proper catalog repo,\n        // or clone manually and install the folder via the local installer\n    }\n    r => r,\n}","preventionTips":["Only advertise catalog URLs you have verified contain a root skills/ directory","Document the <repo>/skills/<name>/ layout contract for anyone building catalogs","Fall back to local-source install when a repo has skills in a nonstandard place"],"tags":["skills","catalog","registry","not-found"],"backgroundTag":"skill-not-in-catalog","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}