{"record":{"id":"027d4d50d0d4d713","repo":"siyuan-note/siyuan","slug":"skill-not-found-s","errorCode":null,"errorMessage":"skill not found: %s","messagePattern":"skill not found: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/skill.go","lineNumber":245,"sourceCode":"\nfunc findSkillRecord(records []skillRecord, name string) (skillRecord, bool) {\n\tkey := skillKey(name)\n\tfor _, record := range records {\n\t\tfor _, alias := range skillAliases(record) {\n\t\t\tif alias == key {\n\t\t\t\treturn record, true\n\t\t\t}\n\t\t}\n\t}\n\treturn skillRecord{}, false\n}\n\n// LoadSkill 按技能名加载正文，或按“技能名/相对路径”加载单个文本资源。\nfunc LoadSkill(locator string, enabledUserSkills []string) (*SkillLoadResult, error) {\n\tname, resource := splitSkillLocator(locator)\n\trecord, ok := findSkillRecord(resolveSkillRecords(enabledUserSkills), name)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"skill not found: %s\", name)\n\t}\n\n\tskillDir := filepath.Join(record.Root, record.DirName)\n\tresult := &SkillLoadResult{\n\t\tName:     name,\n\t\tContent:  record.Body,\n\t\tSkillDir: skillDir,\n\t}\n\tif resource == \"\" {\n\t\tresult.Resources, result.ResourcesTruncated = listSkillResources(skillDir)\n\t\treturn result, nil\n\t}\n\n\tresource, err := normalizeSkillResourcePath(resource)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif resource == \"SKILL.md\" {","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/skill.go#L227-L263","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nres, err := util.LoadSkill(\"code-review\", enabled) // skill not found: code-review\n// after\ndiscovered := util.DiscoverSkills(enabled)\n// discovered shows name \"code-reviewer\"\nres, err := util.LoadSkill(\"code-reviewer\", enabled)","handlingStrategy":"validation","validationCode":"func hasSkill(name string, enabled []string) bool {\n  for _, rec := range util.DiscoverSkills(enabled) {\n    if rec.Name == name { return true }\n  }\n  return false\n}\n// call util.LoadSkill only if hasSkill(name, enabled)","typeGuard":null,"tryCatchPattern":"res, err := util.LoadSkill(locator, enabled)\nif err != nil && strings.HasPrefix(err.Error(), \"skill not found\") {\n  return fmt.Errorf(\"unknown skill %q — list available skills first\", locator)\n}","preventionTips":["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"],"tags":["skills","ai","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}