siyuan-note/siyuan · critical

cannot rebuild encrypted indexes: %w

Error message

cannot rebuild encrypted indexes: %w

What it means

When the encrypted SQLite/blocktree index files for a box fail to open, openEncryptedBoxIndexes falls back to rebuilding them: it closes the DBs, re-authenticates every encrypted document with the box DEK, then recreates the index files. If authenticateEncryptedIndexDocuments fails, the rebuild is aborted and wrapped with "cannot rebuild encrypted indexes: %w". The underlying error usually indicates a document that cannot be decrypted or parsed with the given DEK.

Source

Thrown at kernel/model/encrypted_index.go:35

	"github.com/siyuan-note/siyuan/kernel/util"
)

// openEncryptedBoxIndexes 只在源文档认证成功后重建不兼容或损坏的派生索引,保留源密文和密钥材料。
// 调用方持有笔记本写锁,且已验证密钥包络和笔记本元数据。
func openEncryptedBoxIndexes(boxID string, dek []byte) error {
	open := func() error {
		if err := sql.OpenEncryptedDB(boxID, dek); err != nil {
			return err
		}
		return treenode.OpenEncryptedBlockTreeDB(boxID, dek)
	}
	if err := open(); err == nil {
		return nil
	}
	sql.CloseEncryptedDB(boxID)
	treenode.CloseEncryptedBlockTreeDB(boxID)
	if err := authenticateEncryptedIndexDocuments(boxID, dek); err != nil {
		return fmt.Errorf("cannot rebuild encrypted indexes: %w", err)
	}
	sql.RemoveEncryptedDBFile(boxID)
	treenode.RemoveEncryptedBlockTreeDBFile(boxID)
	if err := open(); err != nil {
		sql.RemoveEncryptedDBFile(boxID)
		treenode.RemoveEncryptedBlockTreeDBFile(boxID)
		return err
	}
	return nil
}

func authenticateEncryptedIndexDocuments(boxID string, dek []byte) error {
	boxDir := filepath.Join(util.DataDir, boxID)
	ids := map[string]struct{}{}
	return filepath.WalkDir(boxDir, func(filePath string, entry fs.DirEntry, walkErr error) error {
		if walkErr != nil {
			return walkErr
		}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Read the wrapped %w cause: if it is an authentication/decrypt failure, the document ciphertext does not match the current DEK — restore the document from backup/sync history.
  2. Verify the box was unlocked with the correct passphrase and that no key-envelope migration is pending or half-applied.
  3. Remove or quarantine the offending .sy file and retry the open so the rebuild can complete, then restore that document from sync.
  4. If the cause is a parse error, check whether the .sy file is truncated and re-fetch it from the sync repo.

Example fix

// before
err := model.OpenBox(boxID) // "cannot rebuild encrypted indexes: authenticate ... failed"
// after
if err := model.UnlockBox(boxID, passphrase); err != nil { return err }
if err := model.OpenBox(boxID); err != nil {
    log.Logf("rebuild failed: %v; restoring doc from sync", err)
}
Defensive patterns

Strategy: retry

Try / catch

if err := model.OpenBox(boxID); err != nil {
    var rebuildErr *fmt.WrapError // inspect wrapped cause
    log.Logf("encrypted index rebuild failed: %v", err)
    // if cause is decrypt/auth failure: restore doc from sync, then retry
}

Prevention

When it happens

Trigger: Opening a box whose siyuan.db or blocktree.db is missing/corrupt triggers the rebuild path; during the rebuild, authenticateEncryptedIndexDocuments hits a .sy file whose decryption (wrong DEK), authentication (tampered ciphertext/AAD), or parsing fails.

Common situations: Index files deleted or corrupted by a crash or manual cleanup while documents remain; DEK/key-envelope mismatch after a failed or partial key migration; manually copied .sy files from another workspace or a different key generation into the box data directory.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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