gastownhall/beads · error

failed to open migration connection: %w

Error message

failed to open migration connection: %w

What it means

After successfully parsing the DSN, openMigrationDB calls sql.Open("mysql", cfg.FormatDSN()); this error wraps that failure. sql.Open mostly validates driver registration and DSN format, so failures here are rare and indicate the mysql driver is not registered or the formatted DSN is still invalid.

Source

Thrown at internal/storage/dolt/store.go:2749

	}
	defer migDB.Close()
	return initSchemaOnDBWithRetry(ctx, migDB)
}

// openMigrationDB opens a one-off connection pool for schema migrations with no
// read/write timeout. Migrations may run far longer than the default 10s pool
// timeout, and timing out part-way leaves the database in a dirty, half-migrated
// state. The single connection is closed by the caller once migration completes.
func (s *DoltStore) openMigrationDB() (*sql.DB, error) {
	cfg, err := mysql.ParseDSN(s.connStr)
	if err != nil {
		return nil, fmt.Errorf("failed to parse DSN for migration connection: %w", err)
	}
	cfg.ReadTimeout = 0
	cfg.WriteTimeout = 0
	db, err := sql.Open("mysql", cfg.FormatDSN())
	if err != nil {
		return nil, fmt.Errorf("failed to open migration connection: %w", err)
	}
	db.SetMaxOpenConns(1)
	return db, nil
}

// rebuildPoolAfterMigration replaces the main connection pool (s.db) after a
// migrating open. Migrations run over a separate one-off pool
// (openMigrationDB); a connection already pooled in s.db before migrations
// ran (e.g. the startup Ping in newServerMode) stays pinned to the
// pre-migration Dolt session root, so the first read through it returns 0
// rows / table-not-found and does not self-heal on retry (be-itm5). A
// non-migrating open (applied == 0 — the common re-open-of-an-
// already-migrated-database path) has no stale state to fix and must return
// before touching s.db or dialing anything.
func (s *DoltStore) rebuildPoolAfterMigration(ctx context.Context, applied int) error {
	if applied == 0 {
		return nil
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Ensure the mysql driver is imported somewhere in the binary: import _ "github.com/go-sql-driver/mysql"
  2. Print/inspect cfg.FormatDSN() for malformed output and fix the source config
  3. Verify the build includes the mysql driver (not an alternative pure-build without it)

Example fix

// before
import (
    "database/sql"
)
// after
import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)
Defensive patterns

Strategy: validation

Validate before calling

// fail fast at startup if the mysql driver isn't registered
if db, err := sql.Open("mysql", "user:pass@tcp(127.0.0.1:3306)/probe"); err != nil {
    panic(fmt.Sprintf("mysql driver missing: %v", err))
} else {
    db.Close()
}

Prevention

When it happens

Trigger: sql.Open returning an error when the mysql driver was never imported/registered (missing import of the driver package in the binary), or FormatDSN producing an invalid string from corrupted cfg fields.

Common situations: Refactoring removed the blank import _ "github.com/go-sql-driver/mysql" so the driver is unregistered; building with a driver-less storage build tag; programmatically corrupted cfg (empty host, invalid timeout strings).

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/4ed7af22b3939c62. Report an issue: GitHub.