siyuan-note/siyuan · error
encrypted attribute view snapshot is missing notebook…
Error message
encrypted attribute view snapshot is missing notebook context
What it means
decryptHistoricalAttributeView validates snapshot data before decryption. If the snapshot was located without a notebook (boxID is empty — the workspace-global storage/av path matched) but the file content is ciphertext, the kernel has no notebook key context to decrypt it with, so it fails with this error. Plaintext data is returned as-is; encrypted data always requires its owning notebook.
Solutions
- Locate the snapshot copy inside its notebook directory (historyDir/<boxID>/storage/av/<avID>.json) so the boxID is available for decryption.
- Regenerate a history snapshot from the encrypted notebook so the AV file is stored with notebook context.
- If the data is genuinely not sensitive, re-save the attribute view so the snapshot is written unencrypted only if that matches your notebook encryption policy (normally not).
- Do not hand-edit or re-encrypt history files; use the documented recovery path in docs/ENCRYPTED-NOTEBOOK.md.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await renderHistoryAttributeView(avID, created);
} catch (e) {
if (String(e.msg).includes("missing notebook context")) {
// retry with the snapshot copy stored under its notebook directory (boxID available)
}
} Prevention
- Keep encrypted-notebook attribute views stored inside their notebook directory, never at the workspace-global storage/av path
- Follow docs/ENCRYPTED-NOTEBOOK.md when moving or restoring encrypted databases
When it happens
Trigger: A history snapshot contains an encrypted attribute view file at the global path historyDir/storage/av/<avID>.json (no boxID derivable) while the source notebook had encryption enabled. This happens when a database belonging to an encrypted notebook was indexed/stored globally instead of inside its notebook directory.
Common situations: Encrypted-notebook users inspecting history of a database that was moved to the workspace level; snapshots produced by a version that misplaced encrypted AV data in the global storage path; corrupted or re-parented history trees after manual data directory manipulation.
Related errors
- encrypted attribute view snapshot has no matching notebook
- encrypted notebook attribute view history is plaintext
- encrypted notebook attribute view snapshot is plaintext
- invalid historical notebook encryption key
- accessing assets in encrypted notebook
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/736cef917e3a0899.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_render.go:1492
if err = gulu.JSON.UnmarshalJSON(data, attrView); err != nil {
logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
return
}
if err = av.CheckSpec(attrView); nil != err {
return
}
attrView.CustomColorRenderContext = newHistoryAttributeViewCustomColorRenderContext(source.historyDir)
attrView.ResolveDirectColors()
viewable, err = renderAttributeView(attrView, "", viewID, carrierViewID, query, page, pageSize, groupPaging, false, false, nil, "")
return
}
func decryptHistoricalAttributeView(boxID, avID string, data []byte) ([]byte, error) {
ciphertext := util.IsCiphertext(data)
if boxID == "" {
if ciphertext {
return nil, errors.New("encrypted attribute view snapshot is missing notebook context")
}
return data, nil
}
if !IsEncryptedBox(boxID) {
if ciphertext {
return nil, fmt.Errorf("encrypted attribute view snapshot has no matching notebook [%s]", boxID)
}
return data, nil
}
if !ciphertext {
return nil, fmt.Errorf("encrypted notebook attribute view snapshot is plaintext [%s]", boxID)
}
return av.DecryptAVData(boxID, avID, data)
}
View on GitHub (pinned to 9f775e8a12)