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

  1. Open data/storage/pinned-docs.json and confirm it contains {"version":1,"docs":[...]}
  2. Fix or remove the invalid version/docs field, or delete the file to reset pins to empty
  3. Restore pinned-docs.json from a working backup or from sync history
  4. 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

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


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)