siyuan-note/siyuan · error
Conf.Language(314)
Error message
Conf.Language(314)
What it means
When reading encrypted document history the kernel needs the notebook's DEK. GetDEKIfUnlocked returns an error when the DEK is unavailable, most commonly because the notebook is locked (not unlocked with its passphrase). The kernel then surfaces Conf.Language(314): 'Please unlock the encrypted notebook first'.
Source
Thrown at kernel/model/history.go:195
relPath := strings.TrimPrefix(filepath.ToSlash(historyPath), filepath.ToSlash(util.HistoryDir))
relPath = strings.TrimPrefix(relPath, "/")
pathParts := strings.SplitN(relPath, "/", 3)
ciphertext := util.IsCiphertext(data)
if ciphertext {
if len(pathParts) < 3 || !ast.IsNodeIDPattern(pathParts[1]) {
err = errors.New("encrypted document history is missing notebook context")
return
}
histBoxID := pathParts[1]
if !IsEncryptedBox(histBoxID) {
err = fmt.Errorf("encrypted document history has no matching notebook [%s]", histBoxID)
return
}
HoldBoxReadLock(histBoxID)
defer ReleaseBoxReadLock(histBoxID)
dek, dekErr := GetDEKIfUnlocked(histBoxID)
if dekErr != nil {
err = errors.New(Conf.Language(314))
return
}
data, err = DecryptFile(histBoxID, pathParts[2], dek, data)
if err != nil {
logging.LogErrorf("decrypt history [%s] failed: %s", historyPath, err)
return
}
} else if len(pathParts) >= 2 && IsEncryptedBox(pathParts[1]) {
err = fmt.Errorf("encrypted notebook document history is plaintext [%s]", pathParts[1])
return
}
isLargeDoc = 1024*1024*1 <= len(data)
luteEngine := NewLute()
if err = treenode.CheckSpecJSON(data); nil != err {
return
}
historyTree, err := dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)View on GitHub (pinned to 8641553a1f)
Solutions
- Unlock the encrypted notebook (open it / enter passphrase) and retry reading the history
- Ensure the notebook is not closed; open it before requesting history content
- If unlock fails, verify the access key / passphrase for the notebook
Defensive patterns
Strategy: retry
Validate before calling
const box = (await fetchPost('/api/notebook/lsNotebooks', {})).notebooks.find(n => n.id === boxID);
if (box && box.closed) await fetchPost('/api/notebook/openNotebook', {notebook: boxID}); // triggers unlock flow Try / catch
try {
return await fetchPost('/api/history/getDocHistoryContent', {historyPath});
} catch (e) {
if (String(e.msg).includes('unlock the encrypted notebook')) {
await promptUnlock(boxID); // user enters passphrase
return fetchPost('/api/history/getDocHistoryContent', {historyPath}); // retry once
} else throw e;
} Prevention
- Unlock encrypted notebooks before scripted history reads
- Queue history operations until after the unlock prompt resolves
- Surface the 'please unlock' message to the user rather than failing silently
When it happens
Trigger: Opening a history snapshot of an encrypted notebook that is currently locked; accessing history right after app boot before the user unlocked the notebook; DEK cache cleared after re-key operations.
Common situations: Browsing history panel while the encrypted notebook is locked; scripted history export running before unlock; a resumed session where the notebook was re-locked by idle timeout.
Related errors
- Please unlock the encrypted notebook first
- encrypted document history is missing notebook context
- encrypted document history has no matching notebook [%s]
- encrypted notebook document history is plaintext [%s]
- Query asset failed [%s]
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/d5136649ac2012c4.
Report an issue: GitHub.