siyuan-note/siyuan · error

parse json [ ] to tree failed

Error message

parse json [%s] to tree failed: %w

What it means

fixTreeJSONData (used by LoadTreeWithFix) parses decrypted .sy JSON into a tree with dataparser.ParseJSON. If parsing fails, the file's JSON is not a valid SiYuan document tree, and the raw cause is wrapped with the box+path of the offending file. Unlike LoadTreeByData this path cannot auto-repair, so it hard-fails.

Solutions

  1. Inspect the wrapped cause to see the JSON syntax/schema error and fix the .sy file accordingly.
  2. Restore the .sy from sync history, file history, or a backup.
  3. If the doc is unrecoverable, remove the broken .sy and let the rest of the notebook index; recreate the document.

Example fix

// before: truncated .sy ending in {"ID":"..." (no closing brace)
// after: restore valid JSON from history: complete the object or copy the file from ~/.siyuan/history
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: probe before load
if err := treenode.CheckSpecJSON(data); err != nil { /* file invalid — restore from history */ }

Try / catch

tree, err := filesys.LoadTreeWithFix(box, p, luteEngine)
if err != nil && strings.Contains(err.Error(), "parse json") {
    // restore .sy from file history or mark doc as broken
}

Prevention

When it happens

Trigger: Loading a document whose .sy content is malformed JSON, an empty/zero-byte file, or a file whose schema cannot be repaired by dataparser — via kernel load paths using LoadTreeWithFix.

Common situations: Interrupted writes leaving truncated .sy files, manual edits breaking JSON syntax, sync conflicts merging two versions incorrectly, or files damaged by disk errors.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/6bda6cecc88883ba. Report an issue: GitHub.

Appendix: source

Thrown at kernel/filesys/tree.go:632

func afterWriteTree(tree *parse.Tree) {
	docIAL := parse.IAL2Map(tree.Root.KramdownIAL)
	cache.PutDocIALInBox(tree.Path, tree.Box, docIAL)
}

// fixTreeJSONData 订正树 JSON 数据。
func fixTreeJSONData(boxID, p string, jsonData []byte, luteEngine *lute.Lute, dek []byte, encrypted bool) (data []byte, needFix bool, err error) {
	if err = treenode.CheckSpecJSON(jsonData); nil != err {
		return
	}
	jsonData, needFix = removeUnescapedUnicodeNull(jsonData)
	ret, parseNeedFix, err := dataparser.ParseJSON(jsonData, luteEngine.ParseOptions)
	if parseNeedFix {
		needFix = true
	}
	if err != nil {
		logging.LogErrorf("parse json [%s] to tree failed: %s", boxID+p, err)
		err = fmt.Errorf("parse json [%s] to tree failed: %w", boxID+p, err)
		return
	}

	ret.Box = boxID
	ret.Path = p

	if err = treenode.CheckSpec(ret); nil != err {
		return
	}
	if err = treenode.RefreshTableCellRichProjection(ret.Root); nil != err {
		return
	}

	if treenode.UpgradeSpec(ret) {
		needFix = true
	}

	// v3.5.1 https://github.com/siyuan-note/siyuan/pull/16657 引入的问题,属性值未转义

View on GitHub (pinned to 9f775e8a12)