siyuan-note/siyuan · error
unsupported skill operation
Error message
unsupported skill operation
What it means
ManageSkillFiles dispatches on request.Action and only accepts the fixed verbs list/read/write/create/mkdir/move/remove. Any other action string is rejected with this error before the storage root is even opened. It is a typo/contract guard for the skill management API surface.
Solutions
- Use exactly one of: "list", "read", "write", "create", "mkdir", "move", "remove"
- Map "delete" to "remove" and "rename" to "move"
- Check the request casing (verbs are lowercase)
Example fix
// before
ManageSkillFiles(SkillFileRequest{Action: "delete", Path: "my-skill"})
// after
ManageSkillFiles(SkillFileRequest{Action: "remove", Path: "my-skill", Revision: rev}) Defensive patterns
Strategy: validation
Validate before calling
var validSkillActions = map[string]bool{"list":true,"read":true,"write":true,"create":true,"mkdir":true,"move":true,"remove":true}
if !validSkillActions[req.Action] { return fmt.Errorf("unsupported action %q", req.Action) } Type guard
func isSkillAction(a string) bool {
switch a { case "list","read","write","create","mkdir","move","remove": return true }
return false
} Try / catch
if err := ManageSkillFiles(req); err != nil && strings.Contains(err.Error(), "unsupported skill operation") {
// log req.Action and map it to a supported verb
} Prevention
- Use the exact lowercase verbs list/read/write/create/mkdir/move/remove
- Map delete->remove and rename->move in client adapters
- Keep request builders in one module so verb names stay centralized
When it happens
Trigger: Calling ManageSkillFiles (or the manageSkillsContract HTTP endpoint) with an Action value other than the seven supported ones — e.g. "delete", "rename", "touch", "listAll", or a capitalized/misspelled verb.
Common situations: Translating code from another file API that uses "delete"/"rename" instead of "remove"/"move"; typos or case mismatches when hand-writing API requests; plugin code written against an older draft of the API.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- create a skill before creating its subdirectories
- only text files inside a skill can be edited
- rename or delete the skill directory instead of SKILL.md
- Access to encrypted notebook data is not supported via this…
- AI editor action must not be empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/9474621deee44a36.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/skill_manage.go:298
if revision == "" || revision != currentRevision {
return errors.New("skill changed; reload it before saving, renaming or deleting")
}
if err = root.Rename(target, p); err != nil {
return err
}
}
complete = true
return nil
}
func ManageSkillFiles(request SkillFileRequest) (SkillFileData, error) {
skillManagementLock.Lock()
defer skillManagementLock.Unlock()
ret := SkillFileData{}
switch request.Action {
case "list", "read", "write", "create", "mkdir", "move", "remove":
default:
return ret, errors.New("unsupported skill operation")
}
root, err := openManagedSkillsRoot()
if err != nil {
return ret, err
}
defer root.Close()
if request.Action == "list" {
ret.Entries = []SkillFileEntry{}
err = fs.WalkDir(root.FS(), ".", func(p string, entry fs.DirEntry, walkErr error) error {
if walkErr != nil || p == "." {
return walkErr
}
// 未解析或被同名技能遮蔽的目录也保留在列表中,链接只展示而不跟随。
editable := false
if entry.Type().IsRegular() && strings.Contains(p, "/") && validateManagedSkillPath(p) == nil {
if err := checkManagedSkillPath(root, p); err == nil {
_, err = readManagedSkillSource(root, p)
editable = err == nilView on GitHub (pinned to 9f775e8a12)