{"record":{"id":"b18244e9cbec52d6","repo":"siyuan-note/siyuan","slug":"invalid-document-identity-s","errorCode":null,"errorMessage":"invalid document identity [%s]","messagePattern":"invalid document identity \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/filesys/tree.go","lineNumber":364,"sourceCode":"\tdata, err = decryptDataWithDEK(boxID, filepath.ToSlash(relPath), data, dek)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif strict {\n\t\tif err = treenode.CheckSpecJSON(data); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tvar doc struct {\n\t\tID         string\n\t\tType       string\n\t\tProperties map[string]string\n\t}\n\tif err = json.Unmarshal(data, &doc); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse parent document [%s]: %w\", absPath, err)\n\t}\n\tif strict && (doc.ID != util.GetTreeID(absPath) || doc.Type != \"NodeDocument\") {\n\t\treturn nil, fmt.Errorf(\"invalid document identity [%s]\", absPath)\n\t}\n\tif len(doc.Properties) == 0 {\n\t\treturn nil, fmt.Errorf(\"missing parent document properties [%s]\", absPath)\n\t}\n\tfor key, value := range doc.Properties {\n\t\tdoc.Properties[key] = html.UnescapeAttrVal(value)\n\t}\n\treturn doc.Properties, nil\n}\n\nfunc DocIAL(absPath string) (ret map[string]string) {\n\t// 加密笔记本的 .sy 是密文，流式 jsoniter 解析无法处理，需先整体读+解密。\n\t// 反推 boxID：路径形如 <DataDir>/<boxID>/...；非加密笔记本走原流式逻辑。\n\tboxID := docIALBoxID(absPath)\n\tif boxID != \"\" && DEKProvider != nil {\n\t\tdek, encrypted, releaseCryptoLease, leaseErr := acquireCryptoLease(boxID)\n\t\tif leaseErr != nil {\n\t\t\treturn map[string]string{}","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/filesys/tree.go#L346-L382","documentation":"readDocIAL reads a .sy document file to extract its root IAL (inline attributes) after decrypting it. In strict mode it verifies the parsed document's ID matches the ID derived from the file name (util.GetTreeID) and that its type is NodeDocument. If either check fails, the .sy file's content does not correspond to its identity, and the function refuses to return properties.","triggerScenarios":"Calling filesys.ReadDocHPath or readParentDocIAL on a .sy whose root block ID differs from the file name (e.g. file renamed without updating root.ID, or file copied under another name), or whose root type is not NodeDocument, while strict mode is on.","commonSituations":"Hand-copied or renamed .sy files in the data directory, corrupted documents after interrupted sync, or third-party tools that rewrite .sy files without keeping root ID and file name in sync.","solutions":["Make the root block ID in the .sy match the file name: open the doc and verify, or re-export/recreate the document.","Restore the original .sy from sync history or a backup.","Re-index the notebook (rebuild from sources) so identity checks pass on valid data."],"exampleFix":"// renamed copy breaks strict identity\n// before: 20240101120000-abcdefg.sy with root.ID \"20240101120000-xyz1234\"\n// after: rename the file back to 20240101120000-xyz1234.sy, or fix the JSON root.ID to the file-name ID","handlingStrategy":"validation","validationCode":"id := util.GetTreeID(p)\nvar doc struct{ ID, Type string }\n// after reading+decrypting: if doc.ID != id || doc.Type != \"NodeDocument\" { handle mismatch before calling ReadDocHPath }","typeGuard":"func docIdentityOK(docID, docType, pathID string) bool { return docID == pathID && docType == \"NodeDocument\" }","tryCatchPattern":"props, err := filesys.ReadDocHPath(box, p)\nif err != nil && strings.Contains(err.Error(), \"invalid document identity\") {\n    // restore from history or repair root ID\n}","preventionTips":["Never rename or copy .sy files manually; use in-app rename/clone","Keep root.ID and file name identical when generating .sy programmatically","Rely on sync history for recovery instead of hand-editing documents"],"tags":["document","integrity","identity-check"],"backgroundTag":"checksum-mismatch","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"}