Hmbown/CodeWhale · error
skill ' ' not found in Codewhale-owned project/global roots
Error message
skill '{name}' not found in Codewhale-owned project/global roots What it means
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.
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
Example fix
// before
remove_by_name("my_skill")?; // canonical name is "my-skill"
// after
remove_by_name("my-skill")?; // use catalog-canonical name Defensive patterns
Strategy: validation
Validate before calling
fn find_owned_skill(catalog: &SkillCatalog, name: &str) -> Option<&Skill> {
let canonical = canonicalize_name(name);
catalog.owned_skills().iter()
.find(|s| s.id.canonical_name == canonical)
} Try / catch
match find_owned_skill(&catalog, name) {
None => eprintln!("no owned skill named {name}; list skills to see canonical names"),
Some(_) => mutation::execute(request, &ctx)?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- SKILL.md `name` must be a single path-safe segment
- skill ' ' has unknown package digest; refusing mutation
- Agent not found
- Agent not found in the active session
- application not found — call list_apps for exact names/pids
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/d742efb341f86244.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/skills/mutation.rs:498
[] => {
// If the name only exists externally, tell the user to import.
let compatible = scan_with_configured(
ctx.workspace,
ctx.home,
ctx.configured_skills_dir,
SkillAuditMode::Compatible,
None,
);
if compatible.skills.iter().any(|s| {
s.id.canonical_name == canonical
&& s.source_kind == SkillSourceKind::CompatibleExternal
}) {
bail!(
"skill '{name}' exists only in a compatible external root; \
import it with /skills (refusing to write external harness directories)"
);
}
bail!("skill '{name}' not found in Codewhale-owned project/global roots");
}
[only] => {
let DigestState::Known(digest) = &only.digest else {
bail!("skill '{name}' has unknown package digest; refusing mutation");
};
Ok(ResolvedOwnedSkill {
id: only.id.clone(),
digest: digest.clone(),
})
}
_ => bail!(
"skill '{name}' exists in both project and global Codewhale roots; \
specify --project or --global"
),
}
}
fn find_audited_skill(View on GitHub (pinned to 73e0f67d83)