siyuan-note/siyuan · error
skill not found
Error message
skill not found: %s
What it means
LoadSkill resolves a skill locator of the form 'name' or 'name/relative/path' against the discovered skill records (enabled user skills plus built-ins). When no record matches the requested skill name, it returns 'skill not found: %s'.
Solutions
- List available skills (discover/skill list) and copy the exact name
- Enable the skill in the AI settings so it appears in enabledUserSkills
- Verify the skill directory exists in the user skills folder or as a bundled skill
- Retry LoadSkill with the corrected locator, including 'name/resource' form for resources
Example fix
// before
res, err := util.LoadSkill("code-review", enabled) // skill not found: code-review
// after
discovered := util.DiscoverSkills(enabled)
// discovered shows name "code-reviewer"
res, err := util.LoadSkill("code-reviewer", enabled) Defensive patterns
Strategy: validation
Validate before calling
func hasSkill(name string, enabled []string) bool {
for _, rec := range util.DiscoverSkills(enabled) {
if rec.Name == name { return true }
}
return false
}
// call util.LoadSkill only if hasSkill(name, enabled) Try / catch
res, err := util.LoadSkill(locator, enabled)
if err != nil && strings.HasPrefix(err.Error(), "skill not found") {
return fmt.Errorf("unknown skill %q — list available skills first", locator)
} Prevention
- Discover and list skills before referencing them by name
- Enable the skill in AI settings before loading it
- Copy exact skill names (watch case and hyphens) from the skill list
- Refresh discovery after installing, removing, or renaming skill directories
When it happens
Trigger: Calling LoadSkill (or the skillLoad API) with a skill name that is not among discovered records — disabled user skills, misspelled names, or skills absent from both workspace and user skill directories.
Common situations: Typo in the skill name; skill exists but is disabled (not in enabledUserSkills); skill deleted or not installed in the expected skills directory; case mismatch in the name.
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
- AI editor action not found
- 0
- AI configuration is unavailable
- AI editor action must not be empty
- AI editor input is empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/027d4d50d0d4d713.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/skill.go:245
func findSkillRecord(records []skillRecord, name string) (skillRecord, bool) {
key := skillKey(name)
for _, record := range records {
for _, alias := range skillAliases(record) {
if alias == key {
return record, true
}
}
}
return skillRecord{}, false
}
// LoadSkill 按技能名加载正文,或按“技能名/相对路径”加载单个文本资源。
func LoadSkill(locator string, enabledUserSkills []string) (*SkillLoadResult, error) {
name, resource := splitSkillLocator(locator)
record, ok := findSkillRecord(resolveSkillRecords(enabledUserSkills), name)
if !ok {
return nil, fmt.Errorf("skill not found: %s", name)
}
skillDir := filepath.Join(record.Root, record.DirName)
result := &SkillLoadResult{
Name: name,
Content: record.Body,
SkillDir: skillDir,
}
if resource == "" {
result.Resources, result.ResourcesTruncated = listSkillResources(skillDir)
return result, nil
}
resource, err := normalizeSkillResourcePath(resource)
if err != nil {
return nil, err
}
if resource == "SKILL.md" {View on GitHub (pinned to 9f775e8a12)