siyuan-note/siyuan · error
encrypted box db not opened for box
Error message
encrypted box db not opened for box
What it means
queryForBox routes a query to the notebook's dedicated encrypted database when the box is an encrypted notebook. If the box is marked encrypted (IsEncryptedBoxFn) but its DB handle is not currently open (GetEncryptedDB returns nil), the query fails closed instead of silently reading the global database, protecting plaintext leakage.
Solutions
- Unlock / open the encrypted notebook so its DB handle is registered before running box-scoped queries
- Check IsEncryptedBoxFn(boxID) && GetEncryptedDB(boxID)==nil before querying and prompt the user to unlock
- Retry after the box DB is opened
Example fix
// before
rows, err := sql.QueryDocTitles(boxID)
// after
if sql.IsEncryptedBoxFn(boxID) && sql.GetEncryptedDB(boxID) == nil {
return errors.New("unlock the encrypted notebook first")
}
rows, err := sql.QueryDocTitles(boxID) Defensive patterns
Strategy: validation
Validate before calling
if sql.IsEncryptedBoxFn(boxID) && sql.GetEncryptedDB(boxID) == nil {
return errors.New("encrypted notebook is locked; unlock before querying")
} Try / catch
rows, err := sql.QueryDocTitles(boxID)
if err != nil && strings.HasPrefix(err.Error(), "encrypted box db not opened") {
return promptUserToUnlock(boxID)
} Prevention
- Ensure encrypted notebooks are unlocked before indexing/search jobs run
- Check the encrypted-box state before issuing box-scoped SQL
- Handle workspace reload races where DB handles close before queued queries
When it happens
Trigger: Calling QueryBacklinkRefDefsInBox, QueryEmptyContentEmbedBlocksInBox, QueryRootBlockByConditionInBox, queryNames, queryAliases, or queryDocTitles with a boxID of an encrypted notebook that is locked/not yet unlocked.
Common situations: Queries issued before the user unlocked the encrypted notebook; a race where the encrypted DB was closed but the box is still flagged encrypted; referencing a box by stale ID after workspace reload.
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
- encrypted box db not opened for box
- query database-bound blocks in notebook
- 314
- 314
- attribute view not found
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/e4bfd4fb9e9aa320.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/sql/database.go:1527
}
if nil == db {
return nil
}
return db.QueryRow(query, args...)
}
// queryForBox 按 box 路由查询多行。加密笔记本用独立 db,否则用全局 db。boxID 为空走全局。
// 加密笔记本未解锁时返回错误——绝不回退全局库。
func queryForBox(boxID, query string, args ...any) (*sql.Rows, error) {
query = strings.TrimSpace(query)
if "" == query {
return nil, errors.New("statement is empty")
}
if boxDB := GetEncryptedDB(boxID); boxDB != nil {
return boxDB.Query(query, args...)
}
if IsEncryptedBoxFn != nil && IsEncryptedBoxFn(boxID) {
return nil, errors.New("encrypted box db not opened for box " + boxID)
}
if nil == db {
return nil, errors.New("database is nil")
}
return db.Query(query, args...)
}
func queryForBoxContext(ctx context.Context, boxID, query string, args ...any) (*sql.Rows, error) {
query = strings.TrimSpace(query)
if "" == query {
return nil, errors.New("statement is empty")
}
if boxDB := GetEncryptedDB(boxID); boxDB != nil {
return boxDB.QueryContext(ctx, query, args...)
}
if IsEncryptedBoxFn != nil && IsEncryptedBoxFn(boxID) {
return nil, errors.New("encrypted box db not opened for box " + boxID)
}View on GitHub (pinned to 9f775e8a12)