siyuan-note/siyuan · error
encrypted attribute view history is missing notebook context
Error message
encrypted attribute view history is missing notebook context [%s]
What it means
When rolling back a document that contains attribute views (databases) from an encrypted notebook, the kernel needs the AV definition file from history. For encrypted boxes the AV may live under the boxID subdirectory of the history entry; if that file does not exist, the kernel cannot restore the database consistently with the document and fails with this error naming the attribute view ID.
Source
Thrown at kernel/model/history.go:384
if tree == nil {
return errors.New("parse document history failed")
}
if encrypted && tree.Root.ID+".sy" != filepath.Base(historyPath) {
return errors.New("encrypted document history root ID does not match its filename")
}
if nil != tree {
historyDir := filepath.Join(util.HistoryDir, parts[0])
avNodes := tree.Root.ChildrenByType(ast.NodeAttributeView)
for _, avNode := range avNodes {
srcAvPath := filepath.Join(historyDir, "storage", "av", avNode.AttributeViewID+".json")
// 加密笔记本的 AV 定义在笔记本级目录
destAvPath := filepath.Join(util.DataDir, "storage", "av", avNode.AttributeViewID+".json")
if IsEncryptedBox(boxID) {
// 历史目录里 AV 也可能在 boxID 子目录下
boxSrcAvPath := filepath.Join(historyDir, boxID, "storage", "av", avNode.AttributeViewID+".json")
if !gulu.File.IsExist(boxSrcAvPath) {
return fmt.Errorf("encrypted attribute view history is missing notebook context [%s]", avNode.AttributeViewID)
}
srcAvPath = boxSrcAvPath
destAvPath = filepath.Join(util.DataDir, boxID, "storage", "av", avNode.AttributeViewID+".json")
}
if gulu.File.IsExist(destAvPath) {
if copyErr := filelock.CopyNewtimes(srcAvPath, destAvPath); nil != copyErr {
logging.LogErrorf("copy av [%s] failed: %s", srcAvPath, copyErr)
}
cache.RemoveAVData(avNode.AttributeViewID)
}
avIDs = append(avIDs, avNode.AttributeViewID)
}
}
avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)
tree.Box = boxID
tree.Path = filepath.ToSlash(strings.TrimPrefix(destPath, util.DataDir+string(os.PathSeparator)+boxID))View on GitHub (pinned to 8641553a1f)
Solutions
- Ensure the history entry includes storage/av/<avID>.json under the boxID directory before rolling back
- Choose a more recent history snapshot that contains the AV definition
- Restore the missing AV history file from backup, then retry the rollback
- Remove the database block from the document (or accept losing AV rollback) if the AV history is unrecoverable
Example fix
// before: snapshot without AV history ls data/history/20260910/encBox/storage/av/ # missing 20250101120000-av1.json // after: pick a snapshot that includes it ls data/history/20260911/encBox/storage/av/ # 20250101120000-av1.json present, use that entry
Defensive patterns
Strategy: validation
Validate before calling
const avIds = docAvIds // attribute view IDs referenced by the document
for (const avId of avIds) {
const p = `data/history/${dateSeg}/${boxID}/storage/av/${avId}.json`
if (!(await fileExists(p))) throw new Error(`history missing AV file ${avId}`)
} Try / catch
try {
await fetchPost("/api/history/rollbackDocHistory", {historyPath})
} catch (e) {
if (String(e.msg || e).includes("missing notebook context")) {
// select a snapshot that includes storage/av definitions
}
} Prevention
- Roll back to snapshots known to include the document's databases
- Do not delete storage/av files when pruning history manually
- Keep document and AV history generation times aligned by using built-in snapshot flows
When it happens
Trigger: rollbackDocHistory on an encrypted notebook's document containing NodeAttributeView nodes, where data/history/<date>/<boxID>/storage/av/<avID>.json is absent — history was captured before the AV was created, or the history entry lacks the storage/av portion.
Common situations: Rolling back to a very old snapshot that predates the database block; history pruning that removed storage/av files but kept document snapshots; manually cleaning the history directory and deleting AV files.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- check encrypted notebook history failed: %w
- invalid historical notebook encryption key
- encrypted document history root ID does not match its filena
- encrypted attribute view history is missing valid notebook c
- encrypted notebook attribute view history is plaintext [%s]
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/bfc45eb116839914.
Report an issue: GitHub.