siyuan-note/siyuan · error
encrypted document history root ID does not match its filena
Error message
encrypted document history root ID does not match its filename
What it means
GetDocHistoryContent reads a historical .sy snapshot and, when the source notebook is encrypted, verifies that the decrypted tree's root block ID matches the history filename (<rootID>.sy). If the decrypted document's root ID differs from the filename, the snapshot is inconsistent (renamed, corrupted, or wrongly decrypted) and the function aborts rather than serve content that cannot be traced back to the named document.
Source
Thrown at kernel/model/history.go:221
} else if len(pathParts) >= 2 && IsEncryptedBox(pathParts[1]) {
err = fmt.Errorf("encrypted notebook document history is plaintext [%s]", pathParts[1])
return
}
isLargeDoc = 1024*1024*1 <= len(data)
luteEngine := NewLute()
if err = treenode.CheckSpecJSON(data); nil != err {
return
}
historyTree, err := dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)
if err != nil {
logging.LogErrorf("parse tree from file [%s] failed: %s", historyPath, err)
return
}
id = historyTree.Root.ID
rootID = historyTree.Root.ID
if ciphertext && rootID+".sy" != filepath.Base(historyPath) {
return "", "", "", false, errors.New("encrypted document history root ID does not match its filename")
}
if !isLargeDoc {
renderTree := &parse.Tree{Root: &ast.Node{Type: ast.NodeDocument}}
keyword = strings.Join(strings.Split(keyword, " "), search.TermSep)
keywords := search.SplitKeyword(keyword)
var unlinks []*ast.Node
ast.Walk(historyTree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering {
return ast.WalkContinue
}
// 数据历史浏览时忽略内容块折叠状态 https://github.com/siyuan-note/siyuan/issues/5778
n.RemoveIALAttr("heading-fold")
n.RemoveIALAttr("fold")
if highlight && 0 < len(keywords) {View on GitHub (pinned to 8641553a1f)
Solutions
- Verify the history file was not manually renamed: the basename must equal <rootID>.sy of the document inside
- Re-generate history for the document (edit and let the auto-history snapshot run) instead of copying old snapshots
- Confirm the notebook's DEK is the original one — decrypting with a wrong key yields a tree whose ID won't match
- Remove the inconsistent snapshot file if it is unrecoverable and rely on other history entries
Example fix
// before: renamed history file breaks lookup mv data/history/20260910/boxID/oldid.sy data/history/20260910/boxID/newname.sy // after: keep filename in sync with root ID cp data/history/20260910/boxID/<rootID>.sy backup/ && rm data/history/20260910/boxID/newname.sy
Defensive patterns
Strategy: validation
Validate before calling
const base = historyPath.split("/").pop()
// before rolling forward to content rendering, confirm the snapshot belongs to the doc
const docRootId = docId // known document ID
if (!base || !base.startsWith(docRootId) || !base.endsWith(".sy")) throw new Error("history filename does not match document ID") Type guard
function isConsistentHistoryPath(historyPath, rootId) {
return typeof historyPath === "string" &&
historyPath.endsWith(`/${rootId}.sy`)
} Try / catch
try {
const res = await fetchPost("/api/history/getDocHistoryContent", {historyPath})
} catch (e) {
if (String(e.msg || e).includes("does not match its filename")) {
// skip this snapshot; the file was renamed or corrupted
}
} Prevention
- Never manually rename or move files under data/history/
- Let SiYuan generate history snapshots; avoid copying snapshots between notebooks
- Keep notebook DEKs unchanged; rotate keys only with an explicit migration
When it happens
Trigger: Calling getDocHistoryContent (kernel API history/getDocHistoryContent) for a history file under an encrypted notebook whose decrypted root.ID plus '.sy' does not equal filepath.Base(historyPath); e.g. a history file that was renamed, copied between documents, or whose ciphertext decrypts with the wrong/derived key producing a mismatched tree.
Common situations: Hand-editing or moving files inside data/history/; restoring history files from another workspace or notebook; DEK/key rotation leaving stale ciphertext; history snapshots taken before a document ID was regenerated.
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
- check encrypted notebook history failed: %w
- invalid historical notebook encryption key
- encrypted attribute view history is missing notebook context
- master password migration is pending
- Please unlock the encrypted notebook first
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/c62f046ec65c3a92.
Report an issue: GitHub.