{"record":{"id":"f667503b69adfecf","repo":"siyuan-note/siyuan","slug":"missing-parent-document-properties-s","errorCode":null,"errorMessage":"missing parent document properties [%s]","messagePattern":"missing parent document properties \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/filesys/tree.go","lineNumber":367,"sourceCode":"\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{}\n\t\t}\n\t\tdefer releaseCryptoLease()\n\t\tif encrypted {","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/filesys/tree.go#L349-L385","documentation":"readDocIAL expects the .sy root block to carry IAL properties (map of attributes such as title, updated). If the parsed root document has an empty Properties map, there is no usable IAL and the function fails, because callers (ReadDocHPath / readParentDocIAL) need at least the doc's properties to resolve HPath.","triggerScenarios":"Calling ReadDocHPath or readParentDocIAL on a .sy whose root NodeDocument block lacks an IAL attributes map — e.g. a hand-written or truncated .sy JSON without {\"Properties\":{...}} on the root node.","commonSituations":"Manually generated .sy files missing the root IAL, documents truncated mid-write, or documents created by older/external tooling that omits root attributes.","solutions":["Add an IAL to the root document block (at minimum the required properties like title, updated, id) in the .sy JSON.","Restore the .sy from backup or sync history.","Recreate the document in the SiYuan editor so the kernel writes a proper root IAL."],"exampleFix":"// before (root node JSON)\n{\"ID\":\"20240101120000-abc\",\"Type\":\"NodeDocument\"}\n// after\n{\"ID\":\"20240101120000-abc\",\"Type\":\"NodeDocument\",\"Properties\":{\"id\":\"20240101120000-abc\",\"title\":\"Doc\",\"updated\":\"20240101120000\"}}","handlingStrategy":"validation","validationCode":"var doc struct{ Properties map[string]string }\njson.Unmarshal(data, &doc)\nif len(doc.Properties) == 0 { /* repair root IAL before loading */ }","typeGuard":"func hasRootIAL(props map[string]string) bool { return len(props) > 0 }","tryCatchPattern":"props, err := filesys.ReadDocHPath(box, p)\nif err != nil && strings.Contains(err.Error(), \"missing parent document properties\") {\n    // rebuild root IAL or restore file\n}","preventionTips":["Always generate .sy roots with a full IAL (id, title, updated)","Do not strip attributes when post-processing document JSON","Verify externally generated documents open in the editor before bulk use"],"tags":["document","ial","missing-attributes"],"backgroundTag":"empty-required-field","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"}