siyuan-note/siyuan · error
encrypted box db not opened for box %s
Error message
encrypted box db not opened for box %s
What it means
CheckReadonlyStatementInBox validates a SQL statement on the database connection belonging to a specific notebook (box). If the box is marked encrypted but its per-box SQLite database handle has not been opened (GetEncryptedDB returned nil), validation cannot proceed safely and the function fails with this error instead of falling back to the main (non-encrypted) connection.
Source
Thrown at kernel/sql/stmt_validate.go:181
// 注意:若字符串里在语法上还有第二条及以后的语句,本函数只针对「首条」对应的 stmt 做判断,
// 不会拒绝多语句。与 CheckSingleStatement 组合即可得到「单条 + 只读」策略。
// 仅允许 SELECT 和 WITH 查询,避免 SQLite 将 ATTACH、DETACH 和事务控制语句标记为只读后放行。
func CheckReadonlyStatement(stmt string) error {
return checkReadonlyStatement(stmt, db)
}
// CheckAssetContentReadonlyStatement 在资源文件内容数据库连接上检查 SQL 是否只读。
func CheckAssetContentReadonlyStatement(stmt string) error {
return checkReadonlyStatement(stmt, assetContentDB)
}
// CheckReadonlyStatementInBox 在指定笔记本对应的数据库连接上检查 SQL 是否只读。
func CheckReadonlyStatementInBox(stmt, boxID string) error {
targetDB := db
if boxDB := GetEncryptedDB(boxID); nil != boxDB {
targetDB = boxDB
} else if IsEncryptedBoxFn != nil && IsEncryptedBoxFn(boxID) {
return errors.New("encrypted box db not opened for box " + boxID)
}
return checkReadonlyStatement(stmt, targetDB)
}
func checkReadonlyStatement(stmt string, targetDB *sql.DB) error {
if strings.TrimSpace(stmt) == "" {
return errors.New("SQL statement is empty")
}
if !isReadonlyQueryStatement(stmt) {
return errors.New("SQL statement is not a read-only query")
}
if nil == targetDB {
return errors.New("database is nil")
}
ctx := context.Background()
conn, err := targetDB.Conn(ctx)
if err != nil {
return errView on GitHub (pinned to 8641553a1f)
Solutions
- Ensure the encrypted box is unlocked/opened first so GetEncryptedDB(boxID) returns a handle before validating SQL
- Re-trigger opening of the box DB (reload the notebook) and retry the query
- Verify the box ID is correct and the notebook is actually loaded in this workspace
- If you control the code, check GetEncryptedDB(boxID) != nil (or skip validation for closed boxes) before calling CheckReadonlyStatementInBox
Example fix
// before
if err := sql.CheckReadonlyStatementInBox(stmt, boxID); err != nil { ... }
// after
if sql.GetEncryptedDB(boxID) == nil {
return fmt.Errorf("box %s is not open yet", boxID)
}
if err := sql.CheckReadonlyStatementInBox(boxID, stmt); err != nil { ... } Defensive patterns
Strategy: validation
Validate before calling
// Go: only validate when the encrypted box DB is actually open
if sql.GetEncryptedDB(boxID) == nil {
return errors.New("encrypted box not open: " + boxID)
}
err := sql.CheckReadonlyStatementInBox(stmt, boxID) Type guard
func encryptedBoxReady(boxID string) bool { return sql.GetEncryptedDB(boxID) != nil } Try / catch
if err := sql.CheckReadonlyStatementInBox(stmt, boxID); err != nil {
if strings.HasPrefix(err.Error(), "encrypted box db not opened") {
// prompt unlock / reopen the notebook, then retry
}
} Prevention
- Unlock/load encrypted notebooks before issuing SQL against them
- Check GetEncryptedDB(boxID) in preconditions
- Retry after notebook reload instead of failing hard
- Never fall back to the main DB for encrypted boxes
When it happens
Trigger: Calling CheckReadonlyStatementInBox(stmt, boxID) where IsEncryptedBoxFn(boxID) is true but GetEncryptedDB(boxID) is nil — i.e. the encrypted box's DB was never opened (e.g. before unlock/initialization or after it was closed) (kernel/sql/stmt_validate.go:181).
Common situations: Querying an encrypted notebook before the user unlocked it; the encrypted box DB was closed after an error and not reopened; a race where a query arrives during box load; referencing a box ID for an encrypted notebook whose key material is unavailable.
Related errors
- encrypted box db not opened for box %s
- cannot disable encrypted notebook feature while encrypted no
- managed export is unavailable
- view not found
- master password migration is pending
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/a66599c35a5963bf.
Report an issue: GitHub.