siyuan-note/siyuan · error
encrypted notebook attribute view history is plaintext [%s]
Error message
encrypted notebook attribute view history is plaintext [%s]
What it means
When rolling back an AV history for an encrypted notebook (path contains an encrypted boxID), the code requires the history snapshot file itself to be ciphertext. If the stored history JSON is plaintext while the notebook is encrypted, the snapshot violates the encrypted-notebook storage contract and restoring it would write unencrypted attribute-view definitions into an encrypted notebook. The error names the offending boxID so the bad snapshot can be located.
Source
Thrown at kernel/model/history.go:697
}
from := historyPath
// 从路径提取 boxID 判断是否加密笔记本的 AV
relPath := strings.TrimPrefix(filepath.ToSlash(historyPath), filepath.ToSlash(util.HistoryDir))
relPath = strings.TrimPrefix(relPath, "/")
pathParts := strings.SplitN(relPath, "/", 3)
data, readErr := filelock.ReadFile(from)
if readErr != nil {
return readErr
}
ciphertext := util.IsCiphertext(data)
if ciphertext && (len(pathParts) < 3 || !ast.IsNodeIDPattern(pathParts[1]) || !IsEncryptedBox(pathParts[1])) {
return errors.New("encrypted attribute view history is missing valid notebook context")
}
to := filepath.Join(util.DataDir, "storage", "av", filepath.Base(historyPath))
if len(pathParts) >= 2 && IsEncryptedBox(pathParts[1]) {
if !ciphertext {
return fmt.Errorf("encrypted notebook attribute view history is plaintext [%s]", pathParts[1])
}
// 加密笔记本的 AV 定义回滚到笔记本级目录
to = filepath.Join(util.DataDir, pathParts[1], "storage", "av", filepath.Base(historyPath))
if err = os.MkdirAll(filepath.Dir(to), 0755); err != nil {
return
}
}
if err = filelock.CopyNewtimes(from, to); err != nil {
logging.LogErrorf("copy file [%s] to [%s] failed: %s", from, to, err)
return
}
avID := strings.TrimSuffix(filepath.Base(historyPath), ".json")
cache.RemoveAVData(avID)
avBoxID := ""
if len(pathParts) >= 2 && IsEncryptedBox(pathParts[1]) {
avBoxID = pathParts[1]
}View on GitHub (pinned to 8641553a1f)
Solutions
- Replace the plaintext history snapshot at that path with a properly encrypted one from a valid backup
- Do not roll back this snapshot; manually recreate the attribute view inside the encrypted notebook so it is written encrypted
- Verify with util.IsCiphertext (or open the file and confirm it is ciphertext) before attempting rollback again
- Check kernel version: if an older build produced the plaintext history, regenerate history after upgrading
Defensive patterns
Strategy: validation
Validate before calling
const data = await readFile(historyPath);
const isCiphertext = (buf) => !Buffer.from(buf.slice(0, 64)).toString("utf8").trimStart().startsWith("{");
const notebookIsEncrypted = isEncryptedBox(boxIDFromPath);
if (notebookIsEncrypted && !isCiphertext(data)) {
throw new Error("plaintext AV history for encrypted notebook " + boxIDFromPath);
} Prevention
- Only generate AV history snapshots with the same kernel version that supports encrypted notebooks
- Verify snapshot encryption before archiving history directories from encrypted notebooks
- Do not hand-edit or re-serialize AV history JSON files
When it happens
Trigger: Calling RollbackAttributeViewHistory with a history path under an encrypted notebook ID (pathParts[1] passes IsEncryptedBox) but the history file read from disk fails util.IsCiphertext — e.g. the .json was saved in plaintext, produced by old tooling, or partially re-written by a sync/restore process.
Common situations: Restoring history snapshots from a backup made before encrypted-notebook AV support; third-party scripts that copy storage/av JSONs around without encrypting them; a mixed-version workspace where an older kernel wrote plaintext AV history for an encrypted notebook.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- encrypted notebook attribute view snapshot is plaintext [%s]
- encrypted attribute view history is missing notebook context
- encrypted attribute view history is missing valid notebook c
- encrypted notebook document history is plaintext [%s]
- CLI does not support encrypted notebook history
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/46936d57d65d3ccf.
Report an issue: GitHub.