gastownhall/beads · error

failed to rebuild pool after migration: %w

Error message

failed to rebuild pool after migration: %w

What it means

This error wraps a failure from store.rebuildPoolAfterMigration. After initSchema applies migrations (>0 applied), the existing connection pool is pinned to the pre-migration session root; the pool must be rebuilt or subsequent reads return 0 rows / table-not-found (be-itm5). It is thrown when the rebuild itself fails.

Source

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

	}

	// A gateway server owns the schema: it provisions each project at its deployed bd
	// version, so a client must never run migrations (DDL) against it. Treat it like
	// ReadOnly for schema — the forward-drift guard above still protects a stale client
	// binary.
	if !cfg.ReadOnly && !cfg.Gateway {
		applied, err := store.initSchema(ctx, dbFacts.bootstrapHeal)
		if err != nil {
			return nil, fmt.Errorf("failed to initialize schema: %w", err)
		}
		// initSchema runs migrations over a separate pool (openMigrationDB).
		// The Ping above already pinned a connection in store.db to the
		// pre-migration session root; without a rebuild, the first read
		// through that stale connection returns 0 rows / table-not-found
		// and does not self-heal on retry (be-itm5). Only a migrating open
		// (applied > 0) needs this — rebuildPoolAfterMigration no-ops otherwise.
		if err := store.rebuildPoolAfterMigration(ctx, applied); err != nil {
			return nil, fmt.Errorf("failed to rebuild pool after migration: %w", err)
		}
	}

	if isLocalHost(cfg.ServerHost) {
		beadsDir := cfg.BeadsDir
		if beadsDir == "" && cfg.Path != "" {
			beadsDir = filepath.Dir(cfg.Path)
		}
		_ = persistResolvedPortFile(cfg, beadsDir)
	}

	// All writers operate on main — transaction isolation via RunInTransaction
	// replaces the former branch-per-worker approach (BD_BRANCH).
	store.branch = "main"

	// Register observable pool gauges for diagnosing shared-server degradation (GH#3140).
	// These report sql.DB.Stats() on each OTel scrape — no-op when telemetry is off.
	store.registerPoolGauges()

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped err and retry opening the store
  2. Verify server connectivity (bd dolt status)
  3. Restart the bd daemon so open runs again from scratch
  4. Check server logs for connection/session errors at migration time
Defensive patterns

Strategy: retry

Validate before calling

applied, err := store.initSchema(ctx, heal)
if err == nil && applied > 0 {
    if err := db.PingContext(ctx); err != nil { return err } // sanity before rebuild
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "failed to rebuild pool after migration") {
        // close store, wait, reopen from scratch
    }
    return err
}

Prevention

When it happens

Trigger: Opening a DoltStore where migrations were applied (applied > 0) and store.rebuildPoolAfterMigration(ctx, applied) returns an error — e.g. the old pool cannot be drained or new connections to the post-migration database fail.

Common situations: Server became unreachable between migration and rebuild; connection pool exhaustion; Dolt server restarted with a different data dir mid-open.

Related errors


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