siyuan-note/siyuan · error
prepare box conf [%s] failed: %w
Error message
prepare box conf [%s] failed: %w
What it means
Box.SaveConf calls prepareBoxConfForSave(box.ID, conf); on error it returns fmt.Errorf('prepare box conf [%s] failed: %w', confPath, err) where confPath is <DataDir>/<boxID>/.siyuan/conf.json. prepareBoxConfForSave (box_conf_crypto.go:88) can fail for several distinct reasons, all wrapped here: nil conf ('notebook configuration is missing'), saving an encrypted notebook as normal ('encrypted notebook cannot be saved as a normal notebook'), an encrypted box in error state ('encrypted notebook is in an error state'), missing encrypted metadata, or a decryption failure on the metadata-reuse path. The %w lets the caller unwrap the real cause.
Source
Thrown at kernel/model/box.go:287
logging.LogErrorf("parse box conf [%s] failed: %s", confPath, err)
return
}
if ret.Encrypted {
if err = revealBoxMetadataIfUnlocked(box.ID, ret); err != nil {
logging.LogErrorf("decrypt encrypted notebook metadata [%s] failed: %s", box.ID, err)
}
} else {
ret.Icon = filterBoxIcon(ret.Icon)
}
return
}
func (box *Box) SaveConf(conf *conf.BoxConf) error {
confPath := filepath.Join(util.DataDir, box.ID, ".siyuan/conf.json")
persisted, err := prepareBoxConfForSave(box.ID, conf)
if err != nil {
return fmt.Errorf("prepare box conf [%s] failed: %w", confPath, err)
}
newData, err := gulu.JSON.MarshalIndentJSON(persisted, "", " ")
if err != nil {
return fmt.Errorf("marshal box conf [%s] failed: %w", confPath, err)
}
oldData, err := filelock.ReadFile(confPath)
if err != nil {
if err = box.saveConf0(newData); err != nil {
return err
}
return syncBoxConfCryptoBackup(box.ID, persisted)
}
if bytes.Equal(newData, oldData) {
return syncBoxConfCryptoBackup(box.ID, persisted)
}
View on GitHub (pinned to 251596fc0d)
Solutions
- Unwrap the returned error to read the underlying message — the fix depends on which prepareBoxConfForSave branch failed.
- If the box is in EncryptedBoxStateError, re-unlock it (re-enter the passphrase) to clear the state before saving.
- If BoxCrypt is nil while Encrypted=true, do not hand-edit conf.json — re-establish encryption through the UI/CLI.
- Ensure a cached DEK exists (notebook unlocked) before changing encrypted-notebook settings.
Example fix
// before
if err := box.SaveConf(conf); err != nil {
logging.LogErrorf("save conf failed: %s", err)
}
// after: surface the wrapped root cause
if err := box.SaveConf(conf); err != nil {
var root error = err
if u := errors.Unwrap(err); u != nil { root = u }
logging.LogErrorf("save conf failed (root=%s): %s", root, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// For encrypted notebooks, ensure a cached DEK and non-error state before saving.
if model.IsEncryptedBox(boxID) {
if model.GetEncryptedBoxState(boxID) == model.EncryptedBoxStateError { unlockFirst(boxID) }
if _, ok := model.CachedDEKCopy(boxID); !ok { unlockFirst(boxID) }
} Try / catch
// Always unwrap so the real prepareBoxConfForSave cause is visible.
if err := box.SaveConf(conf); err != nil {
log.Errorw("save box conf", "box", box.ID, "err", err, "root", errors.Unwrap(err))
return err
} Prevention
- Keep encrypted notebooks unlocked while their settings are being changed.
- Never hand-edit an encrypted notebook's conf.json.
- Clear EncryptedBoxStateError (re-unlock) before any SaveConf on the box.
When it happens
Trigger: Any notebook configuration change for an encrypted notebook — sort mode, icon, etc. — coming through the filetree/attr flows that call Box.SaveConf (e.g. SetBlockAttrs/BatchSetBlockAttrs setting an 'icon' on a box-doc at blockial.go:192/238), or a direct notebook settings save, when the encryption state is inconsistent (BoxCrypt nil'd while Encrypted=true, box stuck in EncryptedBoxStateError, DEK not cached so metadata can't be reused/encrypted).
Common situations: Unlock failed and left the box in error state; a prior migration cleared BoxCrypt; the conf.json was hand-edited to remove key material; switching encryption off without going through the proper disable flow.
Related errors
- mkdir box conf dir failed: %w
- write box conf [%s] failed: %w
- encrypted notebook key material is missing
- list encrypted notebooks failed: %w
- encrypted notebook is locked, please unlock it first
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/4189937a52e9b032.
Report an issue: GitHub.