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

  1. Ensure the sqlite driver is registered: import _ "modernc.org/sqlite" in the binary (or keep it in store's imports as Open expects)
  2. Run go mod tidy and pin a modernc.org/sqlite version compatible with your Go toolchain
  3. Verify the DSN builder (file: URI + pragmas) was not modified into an invalid query string
  4. 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

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


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/a09e6beed162f907. Report an issue: GitHub.