siyuan-note/siyuan · error
parse encrypted notebook history conf [%s] failed: %w
Error message
parse encrypted notebook history conf [%s] failed: %w
What it means
After a successful read, isEncryptedHistoryBoxDir unmarshals conf.json into conf.BoxConf; invalid JSON is wrapped as 'parse encrypted notebook history conf [%s] failed'. The library throws it because a malformed BoxConf cannot yield a trustworthy Encrypted flag, and guessing 'false' could expose encrypted recovery material to destructive history operations.
Source
Thrown at kernel/model/crypto.go:954
if _, err := os.Stat(backupPath); err == nil {
return true, nil
} else if !os.IsNotExist(err) {
return false, fmt.Errorf("stat encrypted notebook history backup [%s] failed: %w", boxDir, err)
}
confPath := filepath.Join(siyuanDir, "conf.json")
if _, err := os.Stat(confPath); err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, fmt.Errorf("stat encrypted notebook history conf [%s] failed: %w", boxDir, err)
}
data, err := filelock.ReadFile(confPath)
if err != nil {
return false, fmt.Errorf("read encrypted notebook history conf [%s] failed: %w", boxDir, err)
}
var boxConf conf.BoxConf
if err = gulu.JSON.UnmarshalJSON(data, &boxConf); err != nil {
return false, fmt.Errorf("parse encrypted notebook history conf [%s] failed: %w", boxDir, err)
}
return boxConf.Encrypted, nil
}
// cachedDEKs 缓存已解锁加密笔记本的 DEK,按 boxID 索引。
// KEK 不全局缓存("严格每笔记本单独解锁"语义):UnlockBox 临时派生 KEK 解出 DEK 后即丢弃 KEK,
// 仅保留 per-box DEK 供后续读写加解密。
var (
cachedDEKs = map[string][]byte{}
cachedDEKsLock sync.RWMutex
)
// boxLastAccess 记录每个加密笔记本最近一次真实用户交互或显式保活时间(unix 纳秒),供自动锁定 cron 使用。
// key: boxID, value: *atomic.Int64。UnlockBox 成功时初始化,Unmount 时清理。
var boxLastAccess sync.Map
// EnableEncryptedNotebookWithSync 在启用前先完成同步;同步恢复了既有配置时只校验原主密码。
func EnableEncryptedNotebookWithSync(password string) error {View on GitHub (pinned to 8641553a1f)
Solutions
- Open the conf named in [%s] and validate its JSON (jq or any JSON linter) to see the exact syntax error
- Restore a valid conf.json from the live notebook's .siyuan/conf.json or from backup/sync history
- If only the Encrypted flag matters and the file is beyond repair, reconstruct a minimal valid BoxConf JSON with the correct fields
- Fix the write path (free disk space, stop killing the process) so future writes are atomic/complete
Example fix
// before: hand-edited conf.json
{ "name": "My notebook", "encrypted": true, }
// after: valid JSON, no trailing comma
{ "name": "My notebook", "encrypted": true } Defensive patterns
Strategy: validation
Validate before calling
data, err := filelock.ReadFile(confPath)
if err == nil {
var probe map[string]any
if err := json.Unmarshal(data, &probe); err != nil { return fmt.Errorf("conf.json invalid: %w", err) }
} Type guard
func validBoxConfJSON(data []byte) bool { var c conf.BoxConf; return gulu.JSON.UnmarshalJSON(data, &c) == nil } Try / catch
enc, err := isEncryptedHistoryBoxDir(boxDir)
if err != nil && errors.Is(errors.Unwrap(err), jsonErrKind) {
return fmt.Errorf("restore valid conf.json for %s from backup before proceeding", boxDir)
} Prevention
- Never hand-edit conf.json while the kernel is running
- Ensure adequate free disk space so writes are not truncated
- Validate conf.json with a JSON parser after manual edits or sync merges
- Restore conf.json from the live notebook or sync history when corrupted
When it happens
Trigger: Any caller of isEncryptedHistoryBoxDir (encryptedNotebookHistoryBoxDirs, hasEncryptedNotebookDeleteHistory, IsEncryptedHistoryPath) processing a conf.json that is truncated, empty, binary garbage, or hand-edited invalid JSON — typically after an interrupted write, disk-full condition, or manual edit.
Common situations: Kernel killed mid-write to conf.json; full disk producing zero-byte files; users editing conf.json with a text editor and breaking JSON syntax; sync conflict merges concatenating two JSON documents.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- stat encrypted notebook history conf [%s] failed: %w
- parse document history failed: %w
- parse document history failed
- master password migration is pending: Master password change
- master password migration is pending: Master password change
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/72d4b1545cb20b33.
Report an issue: GitHub.