siyuan-note/siyuan · error
encrypted notebook snapshot document is plaintext [%s]
Error message
encrypted notebook snapshot document is plaintext [%s]
What it means
The snapshot document belongs to an encrypted notebook (IsEncryptedBox) but its stored bytes are plaintext. The kernel refuses to read unencrypted content from an encrypted notebook's snapshot store, preserving the guarantee that encrypted notebooks never expose plaintext data at rest.
Source
Thrown at kernel/model/history_diff.go:437
return nil, err
}
ciphertext := util.IsCiphertext(data)
if ciphertext {
if len(pathParts) < 2 || !ast.IsNodeIDPattern(pathParts[0]) || !IsEncryptedBox(pathParts[0]) {
return nil, errors.New("encrypted snapshot document is missing valid notebook context")
}
HoldBoxReadLock(pathParts[0])
defer ReleaseBoxReadLock(pathParts[0])
dek, unlockErr := GetDEKIfUnlocked(pathParts[0])
if unlockErr != nil {
return nil, errors.New(Conf.Language(314))
}
data, err = DecryptFile(pathParts[0], pathParts[1], dek, data)
if err != nil {
return nil, err
}
} else if len(pathParts) > 0 && IsEncryptedBox(pathParts[0]) {
return nil, fmt.Errorf("encrypted notebook snapshot document is plaintext [%s]", pathParts[0])
}
rootID := strings.TrimSuffix(filepath.Base(file.Path), filepath.Ext(file.Path))
tree, err := parseDocVersionTree(data, rootID)
boxID := ""
if 0 < len(pathParts) && ast.IsNodeIDPattern(pathParts[0]) {
boxID = pathParts[0]
}
if err != nil {
return &loadedDocVersion{
title: rootID,
rootID: rootID,
raw: data,
parseErr: err,
large: 1024*1024 <= len(data),
boxID: boxID,
}, nil
}
return &loadedDocVersion{View on GitHub (pinned to 8641553a1f)
Solutions
- Re-snapshot the document so it is encrypted under the notebook's DEK
- Remove the plaintext snapshot and rebuild the snapshot index
- Verify the notebook's encrypted status matches how its data is actually stored
Defensive patterns
Strategy: validation
Validate before calling
if (isEncryptedBox(boxID) && !util.isCiphertext(data)) throw new Error("snapshot must be ciphertext"); Try / catch
try { await api.loadDocVersion(fileID); } catch (e) { if (String(e).includes("is plaintext")) { showToast("Snapshot is corrupt; rebuild snapshots for this notebook"); } } Prevention
- Re-snapshot documents after converting a notebook to encrypted
- Never manually place plaintext files into an encrypted notebook's repo store
- Use only kernel write paths for snapshot data
When it happens
Trigger: Opening a snapshot for an encrypted notebook where the repo-stored .sy content is unencrypted — written by a non-encrypting path or manually uploaded from a plain notebook.
Common situations: Migrating a plain notebook into encrypted storage without re-encrypting snapshots; a bug in snapshot write paths; manually injecting plaintext files into the repo store.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- encrypted attribute view snapshot is missing notebook contex
- encrypted notebook document history is plaintext [%s]
- encrypted snapshot document is missing valid notebook contex
- Related operations are being processed, please try again lat
- Encrypted notebooks do not support this operation
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/bf9d63b495f45126.
Report an issue: GitHub.