siyuan-note/siyuan · error
encrypted document history is missing notebook context
Error message
encrypted document history is missing notebook context
What it means
GetDocHistoryContent reads a history snapshot file. If the file bytes are ciphertext, the history path must contain a notebook ID segment (history/<timestamp>/<boxID>/<file>) so the kernel can find the right notebook. When the path has fewer than 3 parts or the second segment is not a node-ID-shaped notebook ID, it errors with 'encrypted document history is missing notebook context'.
Source
Thrown at kernel/model/history.go:183
historyPath, err = validateHistoryPath(historyPath)
if err != nil {
return
}
data, err := filelock.ReadFile(historyPath)
if err != nil {
logging.LogErrorf("read file [%s] failed: %s", historyPath, err)
return
}
// 加密笔记本的历史是密文,按路径里的 boxID 解密后解析
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)
returnView on GitHub (pinned to 8641553a1f)
Solutions
- Pass the full original historyPath returned by getDocHistoryContent/history listing endpoints, not a reconstructed path
- Verify the path matches history/<ts>/<boxID>/<name> for encrypted notebooks
- Restore or re-index the history directory if it was manually modified
Example fix
// before const p = '/history/20240101120000/index.sy'; // missing boxID segment // after const p = '/history/20240101120000/20240101100000-abc1234567890/index.sy';
Defensive patterns
Strategy: validation
Validate before calling
// expected layout: history/<ts>/<boxID>/<name>
const parts = historyPath.replace(/^\/history\//, '').split('/');
if (parts.length < 3 || !/^[0-9a-v]{20}$/.test(parts[1])) throw new Error('history path missing notebook context'); Type guard
const hasBoxContext = (p) => { const parts = p.replace(/^\/history\//, '').split('/'); return parts.length >= 3 && /^[0-9a-v]{20}$/.test(parts[1]); }; Try / catch
try {
return await fetchPost('/api/history/getDocHistoryContent', {historyPath});
} catch (e) {
if (String(e.msg).includes('missing notebook context')) {
// re-fetch the canonical history path from the history listing API
} else throw e;
} Prevention
- Always use history paths as returned by the history APIs; never assemble them by hand
- Keep the full 3-segment path (ts/boxID/file) for encrypted notebooks
- Do not rename or reorganize files under data/history/
When it happens
Trigger: Requesting a history file whose path lacks the notebook-ID segment, or where pathParts[1] is not a valid node ID, while the file content is detected as ciphertext (util.IsCiphertext).
Common situations: Hand-built history paths in plugins/scripts; very old history layout created before encrypted-notebook support; corrupted or renamed history directories.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- encrypted document history has no matching notebook [%s]
- Conf.Language(314)
- encrypted notebook document history is plaintext [%s]
- history version is not a document
- encrypted document history is missing valid notebook context
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/d892ea0fecc1a2a7.
Report an issue: GitHub.