benbjohnson/litestream · critical

open database: %w

Error message

open database: %w

What it means

shrinkDatabase opens the SQLite database with sql.Open("sqlite3", c.DB+"?_journal_mode=WAL") via the mattn/go-sqlite3 driver. If the driver fails to construct the connection the error is wrapped as `open database: %w`. Note sql.Open does not actually connect; most real failures surface here only for bad DSN construction or missing driver registration, and connection errors can also surface on first use.

Source

Thrown at cmd/litestream-test/shrink.go:71

		"checkpoint", c.Checkpoint,
	)

	return c.shrinkDatabase(ctx)
}

func (c *ShrinkCommand) shrinkDatabase(ctx context.Context) error {
	initialSize, err := getDatabaseSize(c.DB)
	if err != nil {
		return fmt.Errorf("get initial size: %w", err)
	}

	slog.Info("Initial database size",
		"size_mb", initialSize/1024/1024,
	)

	db, err := sql.Open("sqlite3", c.DB+"?_journal_mode=WAL")
	if err != nil {
		return fmt.Errorf("open database: %w", err)
	}
	defer db.Close()

	tables, err := c.getTableList(db)
	if err != nil {
		return fmt.Errorf("get table list: %w", err)
	}

	slog.Info("Found tables", "count", len(tables))

	totalDeleted := int64(0)
	for _, table := range tables {
		deleted, err := c.deleteFromTable(db, table)
		if err != nil {
			slog.Error("Failed to delete from table", "table", table, "error", err)
			continue
		}
		totalDeleted += deleted

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Build with CGO_ENABLED=1 and a C toolchain since mattn/go-sqlite3 requires cgo
  2. Confirm the blank import `_ "github.com/mattn/go-sqlite3"` exists in the built binary
  3. If the binary must be pure-Go, switch the driver to modernc.org/sqlite and the DSN to `file:<path>?_journal_mode=WAL` with driver name "sqlite"
  4. Run `go version -m <binary>` to verify which sqlite driver is linked

Example fix

// before (build)
CGO_ENABLED=0 go build -o litestream-test ./cmd/litestream-test
// after
CGO_ENABLED=1 go build -o litestream-test ./cmd/litestream-test
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the binary links a sqlite driver (requires cgo for mattn/go-sqlite3)
// go version -m ./litestream-test | grep sqlite
// build with: CGO_ENABLED=1 go build ./cmd/litestream-test

Try / catch

if err := runShrink(args); err != nil {
    if strings.Contains(err.Error(), "open database") {
        if strings.Contains(err.Error(), "unknown driver") {
            log.Fatal("binary built without sqlite3 driver; rebuild with CGO_ENABLED=1")
        }
    }
    return err
}

Prevention

When it happens

Trigger: The sqlite3 driver binary (mattn/go-sqlite3, requires CGO) is not registered or cgo is disabled at build time (`CGO_ENABLED=0`), producing 'unknown driver sqlite3'; the DSN string with ?_journal_mode=WAL is malformed; the file exists but is not a valid SQLite database.

Common situations: Building the tool with CGO_ENABLED=0 in a minimal container (very common with Go cross-compilation); using modernc.org/sqlite-only builds where the driver name differs; passing a path containing characters that break the DSN.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/6114d6836934c426. Report an issue: GitHub.