Hmbown/CodeWhale · error
only Codewhale managed skills can be removed
Error message
only Codewhale managed skills can be removed
What it means
remove_skill() only removes skills whose source_kind is SkillSourceKind::CodeWhaleManaged. The library deliberately refuses to delete skills it did not create (user-authored, imported, or external skills), even if they sit under a writable root, to avoid destroying assets outside its management contract. The check runs after resolving the audited skill and confirming its root is writable-owned.
Solutions
- Only call remove_skill on skills created/installed by Codewhale itself; check skill.source_kind == SkillSourceKind::CodeWhaleManaged first
- If the skill is user-authored, delete it manually from its skill directory instead of through this API
- Reinstall the skill through a Codewhale-managed flow so it is marked CodeWhaleManaged, then remove it
- If the skill should be managed but is not, fix its source metadata/registration rather than forcing removal
Example fix
// before
ctx.remove_skill(skill_id, digest)?; // panics on user-authored skill
// after
if skill.source_kind == SkillSourceKind::CodeWhaleManaged {
ctx.remove_skill(skill_id, digest)?;
} else {
std::fs::remove_dir_all(&skill.path)?; // manual removal for non-managed skills
} Defensive patterns
Strategy: validation
Validate before calling
fn is_managed(skill: &Skill) -> bool { skill.source_kind == SkillSourceKind::CodeWhaleManaged } Type guard
fn is_managed_skill(s: &Skill) -> bool { matches!(s.source_kind, SkillSourceKind::CodeWhaleManaged) } Prevention
- Filter skill listings to CodeWhaleManaged before offering remove actions
- Handle non-managed skills with a separate manual-deletion flow
- Log source_kind when removal fails to speed diagnosis
When it happens
Trigger: Calling remove_skill (or remove_and_trust_require_managed_owned / remove_managed_skill / remove_uses_on_disk_dir_not_canonical_name via execute_sync) with a skill_id that resolves to a skill whose source_kind is not CodeWhaleManaged — e.g. a user-authored or imported skill.
Common situations: Developers try to programmatically clean up a directory of mixed skills and hit a skill that was hand-created on disk rather than installed through Codewhale; or a skill was created by an older tool version that marked source_kind differently.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- fleet task ' ' is write-capable but declares no…
- only CodeWhale managed skills can be trusted
- only Codewhale managed skills can be trusted
- refusing to trust skill outside Codewhale-owned roots
- A pinned task provider requires an explicit model
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/a7f22aa8bedd482a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/skills/mutation.rs:945
safe_target_path: safe_display_path(&path, Some(ctx.workspace), ctx.home),
before_digest: before,
after_digest: None,
outcome: SkillMutationOutcome::NetworkDenied(host),
}),
}
}
fn remove_skill(
skill_id: AuditedSkillId,
expected_digest: Option<String>,
ctx: &MutationContext<'_>,
) -> Result<SkillMutationReceipt> {
let (skill, path) = find_audited_skill(ctx, &skill_id)?;
if !skill.root.is_writable_owned() {
bail!("refusing to remove skill outside Codewhale-owned roots");
}
if skill.source_kind != SkillSourceKind::CodeWhaleManaged {
bail!("only Codewhale managed skills can be removed");
}
let skills_dir = validate_owned_skill_path(ctx, &skill, &path)?;
let before = verify_expected_digest(&path, expected_digest.as_deref())?;
let scope = match skill.root.kind {
SkillRootKind::CodeWhaleProject => SkillScope::Project,
SkillRootKind::CodeWhaleGlobal => SkillScope::Global,
_ => SkillScope::Logical,
};
let package_name = on_disk_package_name(&skill_id)?;
validate_owned_skill_path(ctx, &skill, &path)?;
install::uninstall(package_name, &skills_dir)?;
Ok(SkillMutationReceipt {
action: SkillActionKind::Remove,
name: skill_id.canonical_name,
scope,
safe_target_path: safe_display_path(&path, Some(ctx.workspace), ctx.home),
before_digest: before,
after_digest: None,View on GitHub (pinned to 73e0f67d83)