gastownhall/beads · error

rebuild pool after migration: %w

Error message

rebuild pool after migration: %w

What it means

After a migration applied changes, rebuildPoolAfterMigration opens a fresh connection pool with sql.Open using the store's connection string; this error wraps that open failing. As with sql.Open generally, it usually means driver/DSN-level problems rather than server availability (ping failures produce the sibling error at line 2777).

Source

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

}

// 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
	}

	newDB, err := sql.Open("mysql", s.connStr)
	if err != nil {
		return fmt.Errorf("rebuild pool after migration: %w", err)
	}
	applyPoolLimits(newDB, s.cfg)

	if err := newDB.PingContext(ctx); err != nil {
		_ = newDB.Close()
		return fmt.Errorf("rebuild pool after migration: %w", err)
	}

	old := s.db
	s.db = newDB
	return old.Close()
}

// IsClosed returns true if the store has been closed.
func (s *DoltStore) IsClosed() bool {
	return s.closed.Load()
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Validate s.connStr is a well-formed DSN before constructing the store (mysql.ParseDSN in a startup check)
  2. Ensure the mysql driver import is present in the binary
  3. If seen in tests, construct DoltStore with a real ParseDSN-validated connection string

Example fix

// before
if _, err := sql.Open("mysql", s.connStr); err != nil { ... }
// after
if _, err := mysql.ParseDSN(s.connStr); err != nil {
    return fmt.Errorf("invalid connStr: %w", err)
}
newDB, err := sql.Open("mysql", s.connStr)
Defensive patterns

Strategy: validation

Validate before calling

// validate connStr before pool rebuild
if _, err := mysql.ParseDSN(s.connStr); err != nil {
    return fmt.Errorf("cannot rebuild pool, bad connStr: %w", err)
}

Try / catch

// Go: driver-registration failures are permanent; surface at startup
newDB, err := sql.Open("mysql", s.connStr)
if err != nil {
    // do not retry: missing driver / invalid DSN is a build/config bug
    return fmt.Errorf("rebuild pool after migration: %w", err)
}

Prevention

When it happens

Trigger: rebuildPoolAfterMigration invoked with applied>0 migrations, and sql.Open("mysql", s.connStr) errors because the mysql driver is not registered or s.connStr is invalid in a way that survives sql.Open validation (empty string, corrupt).

Common situations: connStr mutated to empty/invalid during runtime reconfiguration; driver not linked into binary; tests constructing DoltStore by hand with a bogus connStr then triggering a migration path.

Related errors


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