siyuan-note/siyuan · error
encrypted notebook asset history is plaintext [%s]
Error message
encrypted notebook asset history is plaintext [%s]
What it means
When rolling back an asset history that lives under an encrypted notebook's history directory, SiYuan requires the stored snapshot to actually be encrypted. The history file content was read and found to lack encryptedAssetMagic (i.e. plaintext) even though the path points into an encrypted notebook, so the rollback is rejected to avoid silently restoring unprotected data into an encrypted notebook.
Source
Thrown at kernel/model/history.go:567
}
from := historyPath
// 从路径提取 boxID 判断是否加密笔记本的资源
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
}
encrypted := bytes.HasPrefix(data, encryptedAssetMagic)
if encrypted && (len(pathParts) < 3 || !ast.IsNodeIDPattern(pathParts[1]) || !IsEncryptedBox(pathParts[1])) {
return errors.New("encrypted asset history is missing valid notebook context")
}
to := filepath.Join(util.DataDir, "assets", filepath.Base(historyPath))
if len(pathParts) >= 2 && IsEncryptedBox(pathParts[1]) {
if !encrypted {
return fmt.Errorf("encrypted notebook asset history is plaintext [%s]", pathParts[1])
}
// 加密笔记本的资源回滚到笔记本级 assets 目录
to = filepath.Join(util.DataDir, pathParts[1], "assets", 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
}
IncSync()
util.PushMsg(Conf.Language(102), 3000)
return nil
}
// validateHistoryPath 校验历史路径是否位于工作区内且属于历史目录。View on GitHub (pinned to 8641553a1f)
Solutions
- Re-create the history snapshot so the asset is re-encrypted at write time, then roll back again
- Remove the stale plaintext history entry and re-generate history for that notebook
- Verify with the notebook encryption migration tooling that the notebook's history was re-encrypted after enabling encryption
- Do not hand-copy plaintext assets into data/history/ of encrypted notebooks
Example fix
// before: plaintext snapshot in encrypted notebook history
// data/history/20240101120000-update/<encryptedBoxID>/assets/img.png
// after: re-generate the snapshot as ciphertext
// data/history/20240101120000-update/<encryptedBoxID>/assets/img.png.enc
rollbackAssetsHistory("data/history/20240101120000-update/<encryptedBoxID>/assets/img.png.enc") Defensive patterns
Strategy: validation
Validate before calling
// Pre-check snapshot content is ciphertext before rollback (read first bytes of the history file)
const head = await readHistoryFileHead(historyPath);
if (isEncryptedNotebook(boxID) && !hasEncryptedMagic(head)) {
throw new Error("plaintext snapshot inside encrypted notebook history");
} Type guard
null
Try / catch
try { await rollbackAssetsHistory(p); } catch (e) { if (String(e.msg).startsWith("encrypted notebook asset history is plaintext")) { await regenerateSnapshotEncrypted(p); await rollbackAssetsHistory(p); } else { throw e; } } Prevention
- Do not hand-copy or decrypt files inside data/history of encrypted notebooks
- Re-run encryption migration for notebooks upgraded from plaintext
- Keep backups of history intact rather than editing snapshots in place
When it happens
Trigger: Calling rollbackAssetsHistory with a historyPath under an encrypted notebook (IsEncryptedBox(pathParts[1]) is true) whose file on disk is plaintext — e.g. the snapshot was written before encryption or was tampered/decrypted externally.
Common situations: Restoring old history snapshots taken before the encrypted-notebook feature; a failed/interrupted encryption migration left plaintext snapshots; manual editing or copying of files inside data/history/; version downgrade/upgrade mixing encrypted and unencrypted history.
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 asset history is missing valid notebook context
- source is not an encrypted asset
- CLI does not support encrypted notebook history
- Conf.Language(314)
- accessing assets in encrypted notebook [%s] is not supported
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/2426131bd22943b7.
Report an issue: GitHub.