siyuan-note/siyuan · error
unsupported pinned documents version
Error message
unsupported pinned documents version [%d]
What it means
readPinnedDocs validates storage/pinned-docs.json and throws "unsupported pinned documents version [%d]" when the stored version field is not 1 or the docs array is missing (null). This guards against corrupt or future-format files written by a newer SiYuan version.
Solutions
- Open data/storage/pinned-docs.json and confirm it contains {"version":1,"docs":[...]}
- Fix or remove the invalid version/docs field, or delete the file to reset pins to empty
- Restore pinned-docs.json from a working backup or from sync history
- If a version upgrade introduced this, downgrade or upgrade SiYuan so versions match
Example fix
// before (corrupt storage file)
{"version":2,"docs":[{"id":"20240101120000-abc1234","notebook":"20240101120000-box5678"}]}
// after (supported schema)
{"version":1,"docs":[{"id":"20240101120000-abc1234","notebook":"20240101120000-box5678"}]} Defensive patterns
Strategy: validation
Validate before calling
// Validate the storage file before loading pinned docs
var raw map[string]any
json.Unmarshal(data, &raw)
v, _ := raw["version"].(float64)
_, ok := raw["docs"]
if v != 1 || !ok { /* reset or repair pinned-docs.json */ } Try / catch
docs, err := GetPinnedDocs()
if err != nil && strings.Contains(err.Error(), "unsupported pinned documents version") {
os.Remove(filepath.Join(util.DataDir, "storage", "pinned-docs.json")) // reset
docs, err = GetPinnedDocs()
} Prevention
- Do not hand-edit pinned-docs.json; use the UI pin actions
- Keep version and docs fields intact if editing manually
- Back up the storage directory before upgrading SiYuan versions
- Treat schema-versioned files as opaque across app versions
When it happens
Trigger: Loading pinned documents (GetPinnedDocs, UpdatePinnedDocs, maintainPinnedDocs) where pinned-docs.json has version != 1 or docs == null — e.g. hand-edited file, truncated/corrupt file, or file written by a newer schema.
Common situations: Manually editing pinned-docs.json and omitting version or docs; restoring a partial file from backup; a newer/older SiYuan version with a different schema wrote the file; JSON with "docs": null.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- invalid pinned document
- invalid session data
- cannot read pinned document
- Conf.Language(142)
- decode existing session data failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/a5929def2dd9f246.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/pinned_docs.go:57
func isPinnableDocument(tree *treenode.BlockTree) bool {
return tree != nil && tree.ID == tree.RootID && tree.Type == "d" && !IsEncryptedBox(tree.BoxID)
}
func readPinnedDocs() (ret pinnedDocsStorage, err error) {
ret = pinnedDocsStorage{Version: 1, Docs: []pinnedDocRef{}}
data, err := filelock.ReadFile(filepath.Join(util.DataDir, "storage", "pinned-docs.json"))
if os.IsNotExist(err) {
return ret, nil
}
if err != nil {
return
}
ret = pinnedDocsStorage{}
if err = json.Unmarshal(data, &ret); err != nil {
return
}
if ret.Version != 1 || ret.Docs == nil {
return ret, fmt.Errorf("unsupported pinned documents version [%d]", ret.Version)
}
seen := map[string]bool{}
for _, doc := range ret.Docs {
if !ast.IsNodeIDPattern(doc.ID) || !ast.IsNodeIDPattern(doc.Notebook) || seen[doc.ID] {
return ret, fmt.Errorf("invalid pinned document [%s]", doc.ID)
}
seen[doc.ID] = true
}
return
}
func writePinnedDocs(data pinnedDocsStorage) error {
encoded, err := json.Marshal(data)
if err != nil {
return err
}
dir := filepath.Join(util.DataDir, "storage")
if err = os.MkdirAll(dir, 0755); err != nil {View on GitHub (pinned to 9f775e8a12)