siyuan-note/siyuan · error
invalid document identity
Error message
invalid document identity [%s]
What it means
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.
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.
Example fix
// renamed copy breaks strict identity // before: 20240101120000-abcdefg.sy with root.ID "20240101120000-xyz1234" // after: rename the file back to 20240101120000-xyz1234.sy, or fix the JSON root.ID to the file-name ID
Defensive patterns
Strategy: validation
Validate before calling
id := util.GetTreeID(p)
var doc struct{ ID, Type string }
// after reading+decrypting: if doc.ID != id || doc.Type != "NodeDocument" { handle mismatch before calling ReadDocHPath } Type guard
func docIdentityOK(docID, docType, pathID string) bool { return docID == pathID && docType == "NodeDocument" } Try / catch
props, err := filesys.ReadDocHPath(box, p)
if err != nil && strings.Contains(err.Error(), "invalid document identity") {
// restore from history or repair root ID
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- encrypted .sy [ ]: base id [ ] != root id [ ]
- block [ ] is not a document
- block [ ] is not a document that can declare a child…
- cannot rebuild encrypted indexes
- checksum manifest digest mismatch
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/b18244e9cbec52d6.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/filesys/tree.go:364
data, err = decryptDataWithDEK(boxID, filepath.ToSlash(relPath), data, dek)
if err != nil {
return nil, err
}
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{}View on GitHub (pinned to 9f775e8a12)