{"record":{"id":"6bda6cecc88883ba","repo":"siyuan-note/siyuan","slug":"parse-json-s-to-tree-failed-w","errorCode":null,"errorMessage":"parse json [%s] to tree failed: %w","messagePattern":"parse json \\[(.+?)\\] to tree failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/filesys/tree.go","lineNumber":632,"sourceCode":"\nfunc afterWriteTree(tree *parse.Tree) {\n\tdocIAL := parse.IAL2Map(tree.Root.KramdownIAL)\n\tcache.PutDocIALInBox(tree.Path, tree.Box, docIAL)\n}\n\n// fixTreeJSONData 订正树 JSON 数据。\nfunc fixTreeJSONData(boxID, p string, jsonData []byte, luteEngine *lute.Lute, dek []byte, encrypted bool) (data []byte, needFix bool, err error) {\n\tif err = treenode.CheckSpecJSON(jsonData); nil != err {\n\t\treturn\n\t}\n\tjsonData, needFix = removeUnescapedUnicodeNull(jsonData)\n\tret, parseNeedFix, err := dataparser.ParseJSON(jsonData, luteEngine.ParseOptions)\n\tif parseNeedFix {\n\t\tneedFix = true\n\t}\n\tif err != nil {\n\t\tlogging.LogErrorf(\"parse json [%s] to tree failed: %s\", boxID+p, err)\n\t\terr = fmt.Errorf(\"parse json [%s] to tree failed: %w\", boxID+p, err)\n\t\treturn\n\t}\n\n\tret.Box = boxID\n\tret.Path = p\n\n\tif err = treenode.CheckSpec(ret); nil != err {\n\t\treturn\n\t}\n\tif err = treenode.RefreshTableCellRichProjection(ret.Root); nil != err {\n\t\treturn\n\t}\n\n\tif treenode.UpgradeSpec(ret) {\n\t\tneedFix = true\n\t}\n\n\t// v3.5.1 https://github.com/siyuan-note/siyuan/pull/16657 引入的问题，属性值未转义","sourceCodeStart":614,"sourceCodeEnd":650,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/filesys/tree.go#L614-L650","documentation":"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.","triggerScenarios":"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.","commonSituations":"Interrupted writes leaving truncated .sy files, manual edits breaking JSON syntax, sync conflicts merging two versions incorrectly, or files damaged by disk errors.","solutions":["Inspect the wrapped cause to see the JSON syntax/schema error and fix the .sy file accordingly.","Restore the .sy from sync history, file history, or a backup.","If the doc is unrecoverable, remove the broken .sy and let the rest of the notebook index; recreate the document."],"exampleFix":"// before: truncated .sy ending in {\"ID\":\"...\" (no closing brace)\n// after: restore valid JSON from history: complete the object or copy the file from ~/.siyuan/history","handlingStrategy":"try-catch","validationCode":"// Go: probe before load\nif err := treenode.CheckSpecJSON(data); err != nil { /* file invalid — restore from history */ }","typeGuard":null,"tryCatchPattern":"tree, err := filesys.LoadTreeWithFix(box, p, luteEngine)\nif err != nil && strings.Contains(err.Error(), \"parse json\") {\n    // restore .sy from file history or mark doc as broken\n}","preventionTips":["Never hand-edit .sy files; use the editor or the API","Enable file history/sync so corrupted files can be restored","Validate JSON after any external tool touches the data directory"],"tags":["json","parse","document"],"backgroundTag":"json-parse-error","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}