siyuan-note/siyuan · error

encrypt notebook metadata failed

Error message

encrypt notebook metadata failed: %w

What it means

During enable-encryption, after deriving the DEK and building the BoxCrypt envelope, the notebook's own metadata (conf.json) is encrypted with encryptBoxMetadata(id, boxConf, dek). If that encryption/write step fails, this wrapped error reports it with the underlying cause. Without encrypted metadata the notebook would be half-converted, so the operation aborts before saving the box conf.

Solutions

  1. Read the wrapped cause in the kernel log to see whether it is a write or cipher error, and fix that root cause (permissions, disk space)
  2. Retry the enable-encryption operation after freeing space / fixing permissions
  3. Check no external sync/backup process is holding files under data/<box>/ during conversion

Example fix

// before
$ siyuan --enable-encryption
encrypt notebook metadata failed: open data/<box>/conf.json: permission denied
// after
sudo chown -R $USER:$USER data/<box>/
$ siyuan --enable-encryption   # succeeds
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the notebook data dir is writable before converting
const fs = require("fs");
fs.accessSync(path.join(workspace, "data", boxID), fs.constants.W_OK);

Try / catch

try {
    await enableNotebookEncryption(boxID, password);
} catch (e) {
    if (String(e.message).includes("encrypt notebook metadata failed")) {
        logRootCause(e); // wrapped %w cause reveals write/cipher error
        fixPermissionsOrDisk();
    }
}

Prevention

When it happens

Trigger: encryptBoxMetadata returns an error — e.g. failure serializing the box conf, failure writing the encrypted metadata file to data/<box>/, or filesystem errors (permissions, disk full) while replacing the plaintext conf with its encrypted form.

Common situations: Workspace directory made read-only by another process; disk quota/full disk during conversion; file lock contention from sync clients watching data/; encryption library failure due to malformed KDF output.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/5d2e1dff8e796284. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/crypto.go:2655

	defer func() {
		if err != nil {
			setEncryptedBoxState(createdBoxID, EncryptedBoxStateError)
			cleanupFailedEncryptedBox(createdBoxID)
			id = ""
		}
	}()

	enc, dek, err := WrapNewDEK(id, kek)
	if err != nil {
		return "", err
	}

	box := &Box{ID: id}
	boxConf := box.GetConf()
	boxConf.Encrypted = true
	boxConf.BoxCrypt = enc
	if err = encryptBoxMetadata(id, boxConf, dek); err != nil {
		return "", fmt.Errorf("encrypt notebook metadata failed: %w", err)
	}
	if err = box.SaveConf(boxConf); err != nil {
		return "", fmt.Errorf("save encrypted notebook conf failed: %w", err)
	}
	if err = writeNotebookCryptBackup(id, enc); err != nil {
		return "", fmt.Errorf("write notebook crypt backup failed: %w", err)
	}
	// 回读校验加密配置已落盘,避免写失败后按普通笔记本处理
	verifyConf := box.GetConf()
	if verifyConf == nil || !verifyConf.Encrypted || verifyConf.BoxCrypt == nil {
		err = errors.New("encrypted notebook metadata verification failed after write")
		return "", err
	}
	markRuntimeEncryptedBox(id)
	invalidateEncryptedPublishAccessCache()

	// 复用刚派生的 DEK 直接开 db + 缓存,省去再次 Argon2id 解锁
	cachedDEKsLock.Lock()

View on GitHub (pinned to 8641553a1f)