siyuan-note/siyuan · warning
invalid pinned document action
Error message
invalid pinned document action
What it means
Validation guard in UpdatePinnedDocs: fires when the action argument is anything other than "pin" or "unpin". The action selects whether documents are added to or removed from the pinned root layer; a misspelled or unsupported action string is the faulting input, caught before the pinnedDocsLock is taken.
Solutions
- Pass exactly "pin" or "unpin" (lowercase) as the action parameter
- Check the client code/plugin for typos or case mismatches and normalize the value
- Consult the current API docs for supported action values if migrating an older integration
Example fix
// before
await fetchPost("/api/filetree/updatePinnedDocs", {ids, action: "Pin"});
// after
const action = wantPin ? "pin" : "unpin";
await fetchPost("/api/filetree/updatePinnedDocs", {ids, action}); Defensive patterns
Strategy: validation
Validate before calling
// Caller-side enum check before invoking the update API
if action != "pin" && action != "unpin" {
return fmt.Errorf("action must be pin or unpin, got %q", action)
} Type guard
func isValidPinnedAction(s string) bool { return s == "pin" || s == "unpin" } Try / catch
err := UpdatePinnedDocs(ids, action, targetID, after)
if err != nil && strings.Contains(err.Error(), "invalid pinned document action") {
// fix the action constant at the call site
} Prevention
- Define pin/unpin action strings as named constants shared by caller and API
- Never pass user-supplied or localized strings as the action value
- Keep API clients in sync with the current endpoint contract
- Add unit tests covering both valid actions and a rejection case
When it happens
Trigger: Calling the pinned-docs update API with action set to any value other than "pin"/"unpin" — e.g. typo ("pinned"), localized string, uppercase ("PIN"), or null/missing parameter.
Common situations: Plugin or script passing a wrong/hardcoded action string; API version mismatch where an older client uses a removed action name; copy-paste errors in automation scripts.
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
- document IDs are required
- Field [mode] must be 0 or 1
- invalid block ref check scope
- AI editor action must not be empty
- all asset mappings failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/69f1748960445e90.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/pinned_docs.go:163
doc.SubFileCount = BoxDocSubFileCount(boxID)
} else {
doc.SubFileCount, err = visibleDocCount(boxID, strings.TrimSuffix(bt.Path, ".sy"), box.docIAL, nil)
if err != nil {
return nil, err
}
}
ret = append(ret, doc)
}
return
}
// 根层顺序独立于源文档顺序,按相对位置更新以保留其他窗口新增的入口。
func UpdatePinnedDocs(ids []string, action, targetID string, after bool) error {
if len(ids) == 0 {
return fmt.Errorf("document IDs are required")
}
if action != "pin" && action != "unpin" {
return fmt.Errorf("invalid pinned document action")
}
pinnedDocsLock.Lock()
defer pinnedDocsLock.Unlock()
stored, err := readPinnedDocs()
if err != nil {
return err
}
selected := map[string]bool{}
refs := []pinnedDocRef{}
for _, id := range ids {
if !ast.IsNodeIDPattern(id) {
return fmt.Errorf("invalid document ID [%s]", id)
}
if selected[id] {
continue
}
selected[id] = true
if action == "unpin" {View on GitHub (pinned to 9f775e8a12)