wavetermdev/waveterm · critical

opening db: %w

Error message

opening db: %w

What it means

MakeDB opens the filestore's SQLite database with sqlx.Open using the go-sqlite3 driver, either an in-memory db (testing) or the WAL-mode file db under the Wave data directory. sqlx.Open validates the driver name and DSN and can fail before any connection is made; this error wraps that failure. Note sqlx.Open is lazy — later connection failures surface on first use, so this error usually indicates a DSN/driver-level problem, while actual file-open errors (bad path, permissions) may appear at first query.

Source

Thrown at pkg/filestore/blockstore_dbsetup.go:70

func GetDBName() string {
	waveHome := wavebase.GetWaveDataDir()
	return filepath.Join(waveHome, wavebase.WaveDBDir, FilestoreDBName)
}

func MakeDB(ctx context.Context) (*sqlx.DB, error) {
	var rtn *sqlx.DB
	var err error
	if useTestingDb {
		dbName := ":memory:"
		log.Printf("[db] using in-memory db\n")
		rtn, err = sqlx.Open("sqlite3", dbName)
	} else {
		dbName := GetDBName()
		log.Printf("[db] opening db %s\n", dbName)
		rtn, err = sqlx.Open("sqlite3", fmt.Sprintf("file:%s?mode=rwc&_journal_mode=WAL&_busy_timeout=5000", dbName))
	}
	if err != nil {
		return nil, fmt.Errorf("opening db: %w", err)
	}
	rtn.DB.SetMaxOpenConns(1)
	return rtn, nil
}

func WithTx(ctx context.Context, fn func(tx *TxWrap) error) error {
	return txwrap.WithTx(ctx, globalDB, fn)
}

func WithTxRtn[RT any](ctx context.Context, fn func(tx *TxWrap) (RT, error)) (RT, error) {
	return txwrap.WithTxRtn(ctx, globalDB, fn)
}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Ensure github.com/mattn/go-sqlite3 is imported (blank import) so the 'sqlite3' driver is registered.
  2. Verify the DSN: log GetDBName() and check the data dir exists and the path has no characters that break the file: URI (encode with url.PathEscape if needed).
  3. Confirm WAVE_DATA_DIR is writable by the running user; create the dir if missing.
  4. If using CGO_ENABLED=0 builds, mattn/go-sqlite3 will not work — use a pure-Go driver or enable CGO.
  5. Since Open is lazy, also wrap the first query/migration errors; make sure migration errors in InitFilestore are not being mistaken for this one.

Example fix

// before
import (
    _ "github.com/mattn/go-sqlite3"
    "github.com/jmoiron/sqlx"
)
// after
import (
    _ "github.com/mattn/go-sqlite3" // must remain: registers the "sqlite3" driver
    "github.com/jmoiron/sqlx"
)
// and validate the dir before MakeDB:
if err := os.MkdirAll(filepath.Dir(GetDBName()), 0o755); err != nil {
    return fmt.Errorf("db dir missing: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

import (
    "database/sql"
    _ "github.com/mattn/go-sqlite3"
)
func sqliteDriverAvailable() bool {
    for _, d := range sql.Drivers() {
        if d == "sqlite3" {
            return true
        }
    }
    return false
}

Try / catch

db, err := MakeDB(ctx)
if err != nil {
    return fmt.Errorf("filestore init failed: %w", err)
}
// Open is lazy: force a real connection to surface path/permission errors now
if err := db.PingContext(ctx); err != nil {
    return fmt.Errorf("db not reachable: %w", err)
}

Prevention

When it happens

Trigger: sqlite3 driver not registered (blank import of github.com/mattn/go-sqlite3 missing); malformed DSN from GetDBName(); in tests, useTestingDb path failing to open ':memory:'. Path/permission problems on the db file typically surface later at first query rather than here.

Common situations: App startup via InitFilestore failing because WAVE_DATA_DIR path contains characters that break the file: DSN (e.g. '?' or '#'); building with a sqlite driver variant that registers a different name; misconfigured data directory.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/35b7bce7f56c33b1. Report an issue: GitHub.