siyuan-note/siyuan · error

initialize encrypted notebook document failed

Error message

initialize encrypted notebook document failed: %w

What it means

This error wraps a failure that occurred while initializing the document structure of an encrypted notebook after it was successfully unlocked. The unlock itself succeeded (the box state was set to unlocked with admission), but `initializeBoxDoc(id)` failed, so the whole unlock operation is aborted by wrapping the underlying cause with `%w`. Callers should inspect the wrapped error to learn the real failure reason (e.g. I/O or tree-format problems).

Solutions

  1. Inspect the wrapped cause with errors.Unwrap / %v of the returned error to find the real failure (I/O, parse, permission).
  2. Verify the notebook data directory exists and is readable/writable by the SiYuan process.
  3. Rebuild the notebook index or restore the notebook from a backup/sync snapshot if the document tree is corrupted.
  4. Check available disk space and file locks on the workspace directory.

Example fix

// before
id, err := model.UnlockEncryptedBox(id, key)
if err != nil { return err }
// after
id, err := model.UnlockEncryptedBox(id, key)
if err != nil {
    logging.LogFatalf("unlock failed: %v", err) // %v prints the wrapped initializeBoxDoc cause
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: check notebook dir exists and is writable before unlocking
if _, err := os.Stat(filepath.Join(util.DataDir, boxID)); err != nil {
    return fmt.Errorf("notebook data missing: %w", err)
}

Try / catch

id, err := model.UnlockEncryptedBox(id, key)
if err != nil {
    var root error
    for e := err; e != nil; e = errors.Unwrap(e) { root = e }
    logging.LogFatalf("unlock/init failed, root cause: %v", root)
    return err
}

Prevention

When it happens

Trigger: Calling the unlock API for an encrypted notebook where `initializeBoxDoc` returns an error — e.g. the box's root `.sy` document cannot be created or parsed after decryption.

Common situations: Corrupted notebook data directory after an interrupted sync or crash; a notebook whose documents were written by an incompatible version; disk-full or permission errors preventing creation of the initial document.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/crypto.go:2693

		cachedDEKsLock.Unlock()
		return "", err
	}
	if err = treenode.OpenEncryptedBlockTreeDB(id, dek); err != nil {
		sql.CloseEncryptedDB(id)
		cachedDEKsLock.Unlock()
		return "", err
	}
	cachedDEKs[id] = dek
	cachedDEKsLock.Unlock()

	// DEK 和加密数据库就绪后允许内部初始化读取密钥,但在笔记本文档创建完成前不接纳外部请求。
	newVal := &atomic.Int64{}
	newVal.Store(time.Now().UnixNano())
	boxLastAccess.Store(id, newVal)
	setEncryptedBoxStateWithAdmission(id, EncryptedBoxStateUnlocked, false)

	if _, err = initializeBoxDoc(id); err != nil {
		return "", fmt.Errorf("initialize encrypted notebook document failed: %w", err)
	}

	setEncryptedBoxState(id, EncryptedBoxStateUnlocked)
	IncSync()
	return id, nil
}

// cleanupFailedEncryptedBox 清理创建失败的加密笔记本,清理目标必须是 DataDir 下的有效笔记本目录。
func cleanupFailedEncryptedBox(boxID string) {
	if !ast.IsNodeIDPattern(boxID) {
		logging.LogErrorf("refuse to cleanup failed encrypted box with invalid ID [%s]", boxID)
		return
	}

	dataDir := filepath.Clean(util.DataDir)
	boxDir := filepath.Clean(filepath.Join(dataDir, boxID))
	if boxDir == dataDir || filepath.Dir(boxDir) != dataDir {
		logging.LogErrorf("refuse to cleanup failed encrypted box outside data directory [%s]", boxDir)

View on GitHub (pinned to 8641553a1f)