siyuan-note/siyuan · critical
read encrypted index setting %s: %w
Error message
read encrypted index setting %s: %w
What it means
CheckEncryptedIndexCompatibility reads six SQLCipher PRAGMA settings (cipher_version, cipher_page_size, kdf_iter, cipher_hmac_algorithm, cipher_kdf_algorithm, cipher_use_hmac) from an encrypted index database to verify schema/key compatibility. This error wraps a failure of the PRAGMA query itself (db.QueryRow(...).Scan), e.g. the database is not a SQLCipher database, is corrupted, or the connection is unusable.
Source
Thrown at kernel/util/encrypted_index.go:21
// SPDX-License-Identifier: AGPL-3.0-or-later
package util
import (
"database/sql"
"encoding/json"
"errors"
"fmt"
)
// CheckEncryptedIndexCompatibility 将索引版本保存在受 SQLCipher 认证的表中,拒绝复用缺少版本或参数不匹配的旧索引。
// schema 由各索引维护,修改表结构时递增;索引重建由已认证源文档的调用方负责。
func CheckEncryptedIndexCompatibility(db *sql.DB, kind string, schema int) error {
settings := map[string]string{}
for _, name := range []string{"cipher_version", "cipher_page_size", "kdf_iter", "cipher_hmac_algorithm", "cipher_kdf_algorithm", "cipher_use_hmac"} {
var value string
if err := db.QueryRow("PRAGMA " + name).Scan(&value); err != nil {
return fmt.Errorf("read encrypted index setting %s: %w", name, err)
}
if value == "" {
return fmt.Errorf("missing encrypted index setting %s", name)
}
settings[name] = value
}
encoded, err := json.Marshal(settings)
if err != nil {
return err
}
var metadataTables int
if err = db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type = 'table' AND name = 'encrypted_index_meta'").Scan(&metadataTables); err != nil {
return err
}
if metadataTables == 0 {
var tables int
if err = db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type = 'table'").Scan(&tables); err != nil {
return errView on GitHub (pinned to 8641553a1f)
Solutions
- Check the wrapped cause (%w) to see whether it is 'file is not a database' (wrong format/key) vs. connection/corruption, then act accordingly.
- If the index predates encrypted-index support, rebuild the index from the authenticated source documents rather than forcing the old db open.
- Restore siyuan.db / blocktree.db from a backup or sync snapshot if the file is corrupted.
- Verify the SQLCipher build/version matches the one that wrote the index (cipher_version mismatch) and keep the key-material configuration unchanged.
Example fix
// before
db, _ := OpenEncryptedDB(path) // may fail: "read encrypted index setting cipher_version: file is not a database"
// after
db, err := OpenEncryptedDB(path)
if err != nil {
log.Warnf("encrypted index incompatible (%v); rebuilding from authenticated source", err)
rebuildIndexFromDocuments(path) // caller-driven rebuild, never plaintext fallback
} Defensive patterns
Strategy: fallback
Validate before calling
// before opening, confirm the file is a SQLCipher database with expected settings:
// PRAGMA cipher_version; -- must return a non-empty value
row := db.QueryRow("PRAGMA cipher_version")
var v string
if err := row.Scan(&v); err != nil || v == "" {
return errors.New("not a compatible encrypted index; rebuild required")
} Try / catch
if err := CheckEncryptedIndexCompatibility(db, kind, schema); err != nil {
log.Errorf("encrypted index incompatible: %v", err)
// never fall back to plaintext; rebuild from authenticated source documents
return fmt.Errorf("encrypted index %s unusable, rebuild required: %w", kind, err)
} Prevention
- Never bypass authentication or fall back to plaintext when this error occurs — rebuild the index from authenticated sources instead.
- Keep encrypted-index format versions and SQLCipher parameters (page size, KDF, HMAC) unchanged across upgrades.
- Maintain recoverable backups/snapshots of siyuan.db and blocktree.db.
- Test upgrades against fixtures from the previous encrypted format to catch compatibility breaks early.
When it happens
Trigger: Calling CheckEncryptedIndexCompatibility (directly or via OpenEncryptedDB / OpenEncryptedBlockTreeDB) on a database where `PRAGMA cipher_version` (or a sibling PRAGMA) cannot be scanned — non-SQLCipher/plain-SQLite file, wrong key already applied, corrupted db header, or a closed/pool-broken connection.
Common situations: Pointing the kernel at an old unencrypted index (pre-encrypted-notebook format); a workspace db corrupted or truncated; SQLCipher build mismatch so PRAGMA functions are unavailable; opening the db after a failed key derivation leaves the connection broken.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- missing encrypted index setting %s
- incompatible encrypted index
- encrypted box db not opened for box
- unsupported encrypted asset container version
- query database-bound blocks in notebook [%s] failed: %w
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/1f0416f9b535279f.
Report an issue: GitHub.