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

  1. Add an IAL to the root document block (at minimum the required properties like title, updated, id) in the .sy JSON.
  2. Restore the .sy from backup or sync history.
  3. 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

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


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)