charmbracelet/crush · error
skill not found
Error message
skill not found
What it means
ErrSkillNotFound is the sentinel error returned by Catalog.FindEffective when the requested skill ID is not part of the effective visible skill set (builtin, user, or project skills currently discovered). Callers should compare with errors.Is.
Source
Thrown at internal/skills/catalog.go:41
Name string `json:"name"`
Description string `json:"description"`
Label string `json:"label"`
Source SourceType `json:"source"`
UserInvocable bool `json:"user_invocable"`
}
// SkillReadResult holds metadata about a skill returned alongside its
// content.
type SkillReadResult struct {
Name string `json:"name"`
Description string `json:"description"`
Source SourceType `json:"source"`
Builtin bool `json:"builtin"`
}
// ErrSkillNotFound is returned when a skill ID is not part of the
// effective visible skill set.
var ErrSkillNotFound = errors.New("skill not found")
// Catalog builds a slice of CatalogEntry values from pre-discovered
// skills. The skillPaths and workingDir parameters are used only for
// labelling (system / user / project); pass nil/empty when labels are
// not needed.
func Catalog(active []*Skill, skillPaths []string, workingDir string) []CatalogEntry {
entries := make([]CatalogEntry, 0, len(active))
for _, skill := range active {
label, source := skillLabel(skillPaths, workingDir, skill)
entries = append(entries, CatalogEntry{
ID: skill.SkillFilePath,
Name: skill.Name,
Description: skill.Description,
Label: label,
Source: source,
UserInvocable: skill.UserInvocable,
})
}View on GitHub (pinned to 7944b8e522)
Solutions
- Run the skill listing (catalog) to see the effective visible skill IDs and use the exact ID
- Fix the ID typo or update the stale reference to the renamed skill
- Ensure the skill directory exists in .agents/skills, user skills dir, or builtin set and passes visibility filtering
Example fix
// before
skill, err := catalog.FindEffective("code-review")
// after
if !catalog.HasSkill("code-review") {
return fmt.Errorf("skill %q not available; check skill config", "code-review")
}
skill, err := catalog.FindEffective("code-review") Defensive patterns
Strategy: type-guard
Validate before calling
for id, ok := range visibleIDs { _ = id; _ = ok }
// before lookup:
if _, ok := catalog.VisibleIDs()[skillID]; !ok {
return fmt.Errorf("unknown skill %q", skillID)
} Type guard
func hasSkill(c *skills.Catalog, id string) bool {
_, err := c.FindEffective(id)
return err == nil
} Try / catch
skill, err := catalog.FindEffective(id)
if errors.Is(err, skills.ErrSkillNotFound) {
// fall back to builtin or report unknown skill
} Prevention
- List effective skills before referencing IDs in config
- Use exact IDs from the catalog output, not display names
- Re-check skill references after renaming or removing skills
When it happens
Trigger: Calling FindEffective(id) with a skill ID that was never discovered, was filtered out as non-visible, or whose source directory no longer exists.
Common situations: Typo in a skill ID in config or an agent prompt; a project skill removed/renamed while stale references remain; skills disabled or excluded so they are not in the effective set; running in a directory without the project skill.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- %w: %s
- read skill %q: %w
- name is required
- name must be alphanumeric with hyphens, no leading/trailing/
- description is required
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/fb5ef68afc5a231b.
Report an issue: GitHub.