siyuan-note/siyuan · error
missing parent document properties
Error message
missing parent document properties [%s]
What it means
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.
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.
Example fix
// before (root node JSON)
{"ID":"20240101120000-abc","Type":"NodeDocument"}
// after
{"ID":"20240101120000-abc","Type":"NodeDocument","Properties":{"id":"20240101120000-abc","title":"Doc","updated":"20240101120000"}} Defensive patterns
Strategy: validation
Validate before calling
var doc struct{ Properties map[string]string }
json.Unmarshal(data, &doc)
if len(doc.Properties) == 0 { /* repair root IAL before loading */ } Type guard
func hasRootIAL(props map[string]string) bool { return len(props) > 0 } Try / catch
props, err := filesys.ReadDocHPath(box, p)
if err != nil && strings.Contains(err.Error(), "missing parent document properties") {
// rebuild root IAL or restore file
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Manually generated .sy files missing the root IAL, documents truncated mid-write, or documents created by older/external tooling that omits root attributes.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- block [ ] is not a document
- block [ ] is not a document that can declare a child…
- Conf.Language(25) + " [" + node.ID + "]"
- Conf.Language(25) + " [" + node.ID + "]" (localized invalid…
- Conf.Language(341)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/f667503b69adfecf.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/filesys/tree.go:367
}
if strict {
if err = treenode.CheckSpecJSON(data); err != nil {
return nil, err
}
}
var doc struct {
ID string
Type string
Properties map[string]string
}
if err = json.Unmarshal(data, &doc); err != nil {
return nil, fmt.Errorf("parse parent document [%s]: %w", absPath, err)
}
if strict && (doc.ID != util.GetTreeID(absPath) || doc.Type != "NodeDocument") {
return nil, fmt.Errorf("invalid document identity [%s]", absPath)
}
if len(doc.Properties) == 0 {
return nil, fmt.Errorf("missing parent document properties [%s]", absPath)
}
for key, value := range doc.Properties {
doc.Properties[key] = html.UnescapeAttrVal(value)
}
return doc.Properties, nil
}
func DocIAL(absPath string) (ret map[string]string) {
// 加密笔记本的 .sy 是密文,流式 jsoniter 解析无法处理,需先整体读+解密。
// 反推 boxID:路径形如 <DataDir>/<boxID>/...;非加密笔记本走原流式逻辑。
boxID := docIALBoxID(absPath)
if boxID != "" && DEKProvider != nil {
dek, encrypted, releaseCryptoLease, leaseErr := acquireCryptoLease(boxID)
if leaseErr != nil {
return map[string]string{}
}
defer releaseCryptoLease()
if encrypted {View on GitHub (pinned to 9f775e8a12)