JuliusBrussee/caveman · critical
open sqlite %q: %w
Error message
open sqlite %q: %w
What it means
Returned by store.Open when sql.Open("sqlite", DSN) itself fails. With modernc.org/sqlite this is almost never a file problem (opening is lazy) — it means the driver name is not registered (blank import missing), the DSN pragmas are malformed, or the pure-Go driver failed to initialize.
Source
Thrown at proxy/internal/store/store.go:268
// client's ORIGINAL bytes for a frozen block it already compressed, flipping the
// upstream prefix mid-conversation.
func sqliteDSN(path string) string {
const pragmas = "_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)"
if path == ":memory:" {
return "file::memory:?" + pragmas
}
// A file: URI so a path containing '?' or '#' cannot be truncated into a
// different database file by the driver's DSN split.
u := url.URL{Scheme: "file", OmitHost: true, Path: path}
return u.String() + "?" + pragmas
}
// Open opens (creating if needed) the SQLite database at path and migrates the
// schema. logger may be nil.
func Open(path string, logger *slog.Logger) (*Store, error) {
db, err := sql.Open("sqlite", sqliteDSN(path))
if err != nil {
return nil, fmt.Errorf("open sqlite %q: %w", path, err)
}
if _, err := db.Exec(schema); err != nil {
_ = db.Close()
return nil, fmt.Errorf("migrate sqlite %q: %w", path, err)
}
if path != ":memory:" {
_ = os.Chmod(path, 0o600)
}
for _, m := range migrations {
if _, err := db.Exec(m); err != nil && !strings.Contains(err.Error(), "duplicate column name") {
_ = db.Close()
return nil, fmt.Errorf("migrate sqlite %q: %w", path, err)
}
}
return &Store{db: db, logger: logger}, nil
}
// Close closes the underlying database.View on GitHub (pinned to 27d5a3981a)
Solutions
- Ensure the sqlite driver is registered: import _ "modernc.org/sqlite" in the binary (or keep it in store's imports as Open expects)
- Run go mod tidy and pin a modernc.org/sqlite version compatible with your Go toolchain
- Verify the DSN builder (file: URI + pragmas) was not modified into an invalid query string
- Check GOOS/GOARCH support for the cgo-free driver if cross-compiling
Example fix
// before: new cmd binary uses store.Open but never registers the driver
import "proxy/internal/store"
// after
import (
"proxy/internal/store"
_ "modernc.org/sqlite"
) Defensive patterns
Strategy: validation
Validate before calling
// Before Open, confirm the driver registers (cheap smoke check at startup)
if _, ok := sql.Open("sqlite", ":memory:").(*sql.DB); !ok {
panic("sqlite driver not registered")
} Try / catch
st, err := store.Open(path, logger)
if err != nil {
if strings.Contains(err.Error(), "open sqlite") {
// driver/DSN problem: check blank import of modernc.org/sqlite and go.mod
log.Error("sqlite driver unavailable; rebuild with the driver linked in", "error", err)
}
} Prevention
- Blank-import _ "modernc.org/sqlite" in every binary that calls store.Open
- Run go mod tidy after driver version changes; keep driver and Go toolchain compatible
- Add a startup smoke test that opens :memory: via the same helper
When it happens
Trigger: Calling store.Open in a binary that does not blank-import the sqlite driver registration (or links an incompatible driver version); a DSN whose query string of pragmas is syntactically rejected; a driver/runtime incompatibility (e.g. modernc.org/sqlite requires specific Go versions).
Common situations: Splitting the store package into a new binary and forgetting the driver's blank import; go.mod tidying away the driver because only a blank import references it; upgrading modernc.org/sqlite to a version needing a newer Go toolchain; building for GOOS/GOARCH the pure-Go driver does not support.
Related errors
- ccr: typed object id collision
- memory %s changed during supersede
- executable identity unsupported on %s
- prefix replacement put: %w
- migrate sqlite %q: %w
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/a09e6beed162f907.
Report an issue: GitHub.