sipeed/picoclaw · error
wrap database: %w
Error message
wrap database: %w
What it means
Thrown by MatrixChannel.initCrypto when dbutil.NewWithDB fails to wrap the raw *sql.DB with mautrix's dbutil layer (pkg/channels/matrix/matrix.go:363). dbutil provides the SQL dialect (the sqliteDriver constant "sqlite" doubles as the dialect label) that the mautrix crypto store uses for its queries and migrations. Failure means the dialect could not be resolved for the driver name or the *sql.DB handle is unusable, and the DB is closed before returning.
Source
Thrown at pkg/channels/matrix/matrix.go:363
// This is equivalent to the "sqlite3-fk-wal" dialect used by cryptohelper
pragmaStmts := []string{
"PRAGMA foreign_keys = ON",
"PRAGMA journal_mode = WAL",
"PRAGMA synchronous = NORMAL",
"PRAGMA busy_timeout = 5000",
}
for _, pragma := range pragmaStmts {
if _, err = db.ExecContext(ctx, pragma); err != nil {
_ = db.Close()
return fmt.Errorf("execute %s: %w", pragma, err)
}
}
// Wrap with dbutil for dialect support
wrappedDB, err := dbutil.NewWithDB(db, sqliteDriver)
if err != nil {
_ = db.Close()
return fmt.Errorf("wrap database: %w", err)
}
cryptoHelper, err := cryptohelper.NewCryptoHelper(c.client, []byte(c.config.CryptoPassphrase), wrappedDB)
if err != nil {
return fmt.Errorf("create crypto helper: %w", err)
}
if c.client.DeviceID == "" {
resp, whoamiErr := c.client.Whoami(ctx)
if whoamiErr != nil {
_ = db.Close()
return fmt.Errorf("get device ID via whoami: %w", whoamiErr)
}
c.client.DeviceID = resp.DeviceID
}
if err = cryptoHelper.Init(ctx); err != nil {
cryptoHelper.Close()View on GitHub (pinned to 49183d7e8d)
Solutions
- Run 'go mod tidy' so maunium.net/go/mautrix, its dbutil, and modernc.org/sqlite versions are consistent
- Confirm sqliteDriver still matches the driver name registered by modernc.org/sqlite ("sqlite") in the linked version
- Inspect the wrapped error with '%w' unwrapping (errors.As/errors.Unwrap) — dbutil reports the concrete rejection reason
- If it persists, test the raw handle first with db.PingContext(ctx) before wrapping to isolate driver-level failure from dialect resolution
Defensive patterns
Strategy: try-catch
Try / catch
// no caller-side pre-check exists; classify at startup and fail fast with the wrapped cause
if err := matrixCh.Start(ctx); err != nil {
if strings.Contains(err.Error(), "wrap database") {
log.Fatalf("dbutil rejected the sqlite dialect; check mautrix/modernc versions are in lockstep: %v", err)
}
return err
} Prevention
- Pin maunium.net/go/mautrix and modernc.org/sqlite together and run 'go mod tidy' after upgrades
- Add a smoke test that boots the Matrix channel with a temp crypto dir in CI to catch dialect regressions
- Never construct the *sql.DB with a different driver name than the dialect you pass on
When it happens
Trigger: Calling dbutil.NewWithDB with a driver/dialect name the linked mautrix version does not recognize; passing a nil or already-closed *sql.DB; version skew between maunium.net/go/mautrix, its dbutil package, and modernc.org/sqlite after a partial dependency upgrade; the *sql.DB opened with a connection string the driver rejects at first use.
Common situations: Upgrading mautrix (go.mod pins maunium.net/go/mautrix v0.27.0) without regenerating go.sum (go mod tidy); swapping the SQLite driver (mattn/go-sqlite3 vs modernc.org/sqlite) so the registered driver name no longer matches the dialect string; vendoring mismatches in downstream forks of this bot.
Related errors
- execute %s: %w
- get device ID via whoami: %w
- create crypto helper: %w
- init crypto helper: %w
- create seahorse engine: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/d4c298949b0fa37c.
Report an issue: GitHub.