{"record":{"id":"d742efb341f86244","repo":"Hmbown/CodeWhale","slug":"skill-name-not-found-in-codewhale-owned-project-global-roots","errorCode":null,"errorMessage":"skill '{name}' not found in Codewhale-owned project/global roots","messagePattern":"skill '(.+?)' not found in Codewhale-owned project/global roots","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/mutation.rs","lineNumber":498,"sourceCode":"        [] => {\n            // If the name only exists externally, tell the user to import.\n            let compatible = scan_with_configured(\n                ctx.workspace,\n                ctx.home,\n                ctx.configured_skills_dir,\n                SkillAuditMode::Compatible,\n                None,\n            );\n            if compatible.skills.iter().any(|s| {\n                s.id.canonical_name == canonical\n                    && s.source_kind == SkillSourceKind::CompatibleExternal\n            }) {\n                bail!(\n                    \"skill '{name}' exists only in a compatible external root; \\\n                     import it with /skills (refusing to write external harness directories)\"\n                );\n            }\n            bail!(\"skill '{name}' not found in Codewhale-owned project/global roots\");\n        }\n        [only] => {\n            let DigestState::Known(digest) = &only.digest else {\n                bail!(\"skill '{name}' has unknown package digest; refusing mutation\");\n            };\n            Ok(ResolvedOwnedSkill {\n                id: only.id.clone(),\n                digest: digest.clone(),\n            })\n        }\n        _ => bail!(\n            \"skill '{name}' exists in both project and global Codewhale roots; \\\n             specify --project or --global\"\n        ),\n    }\n}\n\nfn find_audited_skill(","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/skills/mutation.rs#L480-L516","documentation":"Name-based mutations resolve against Codewhale-owned project and global roots only. If no owned-root skill matches the (canonicalized) name — and no compatible-external copy exists either — the resolver reports the skill as not found in the owned roots and the mutation fails.","triggerScenarios":"execute/execute_sync with a name-based remove/update/trust request where the catalog's owned project+global skills contain no entry whose canonical name matches; the skill exists under a different name, in an incompatible/unregistered directory, or the wrong scope was implied.","commonSituations":"Typo in the skill name or a name-normalization mismatch (e.g. underscores vs hyphens); the skill was installed into a directory the catalog does not scan; the skill was uninstalled earlier; querying global when the skill lives in project (or vice versa) without an explicit scope when a dual-scope disambiguation is required.","solutions":["Run a skill list/catalog query to see the exact names of owned skills and use the canonical name","Check both project and global roots; pass explicit --project or --global scope if the name exists in one of them","Re-import or install the skill into an owned root if it is genuinely missing","Normalize the name (canonical form) before passing it to the mutation API"],"exampleFix":"// before\nremove_by_name(\"my_skill\")?; // canonical name is \"my-skill\"\n// after\nremove_by_name(\"my-skill\")?; // use catalog-canonical name","handlingStrategy":"validation","validationCode":"fn find_owned_skill(catalog: &SkillCatalog, name: &str) -> Option<&Skill> {\n    let canonical = canonicalize_name(name);\n    catalog.owned_skills().iter()\n        .find(|s| s.id.canonical_name == canonical)\n}","typeGuard":null,"tryCatchPattern":"match find_owned_skill(&catalog, name) {\n    None => eprintln!(\"no owned skill named {name}; list skills to see canonical names\"),\n    Some(_) => mutation::execute(request, &ctx)?,\n}","preventionTips":["Normalize skill names (canonical form) before name-based mutations","List the catalog to confirm existence and exact spelling before mutating","Pass explicit project/global scope when both roots may hold skills"],"tags":["skills","not-found","naming","catalog"],"backgroundTag":"entity-not-found","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}