siyuan-note/siyuan · error

save encrypted notebook conf failed

Error message

save encrypted notebook conf failed: %w

What it means

After the metadata is encrypted, box.SaveConf(boxConf) persists the updated box configuration (Encrypted=true, BoxCrypt envelope). If saving fails, this wrapped error aborts the conversion. A notebook whose conf was not saved would still claim to be plain on next load, so the operation must not continue.

Solutions

  1. Check kernel logs for the wrapped cause and fix the underlying write error (permissions, disk space)
  2. Ensure no other process locks data/<box>/conf.json and retry enable-encryption
  3. Verify conf.json is writable: touch data/<box>/conf.json as the user running the kernel

Example fix

// before
encrypt -> save encrypted notebook conf failed: ... disk full
// after
df -h <workspace>          # free space
clean up, then retry the operation
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require("fs");
const confPath = path.join(workspace, "data", boxID, "conf.json");
fs.accessSync(confPath, fs.constants.W_OK);

Try / catch

try {
    await enableNotebookEncryption(boxID, password);
} catch (e) {
    if (String(e.message).includes("save encrypted notebook conf failed")) {
        checkDiskSpaceAndLocks(confPath);
        // retry after fixing; operation aborted safely
    }
}

Prevention

When it happens

Trigger: box.SaveConf fails writing data/<box>/conf.json — permission denied, disk full, path issues, or serialization problems while persisting the box configuration struct.

Common situations: data/ directory owned by root after running the kernel with sudo once; OneDrive/Dropbox/backup tool locking conf.json on Windows; disk quota exceeded on the workspace volume.

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/cac525d38a94164d. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/crypto.go:2658

			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()
	if err = sql.OpenEncryptedDB(id, dek); err != nil {
		cachedDEKsLock.Unlock()
		return "", err

View on GitHub (pinned to 8641553a1f)