gastownhall/beads · error

remote-migrate gate: read current version: %w

Error message

remote-migrate gate: read current version: %w

What it means

Wraps a failure from CurrentVersion while the remote-migrate gate decides whether applying pending schema migrations would fork a remote-backed Dolt database. CurrentVersion treats a missing schema_migrations table as version 0, so this error means the version read itself failed (not that the table is missing). Callers are the CheckRemoteMigrateGate* family used before auto-migration on store open.

Source

Thrown at internal/storage/schema/remote_migrate_gate.go:404

func CheckRemoteMigrateGateForRemoteWithRemoteCheck(ctx context.Context, db DBConn, remoteName string, extraHasRemote func() bool) error {
	return checkRemoteMigrateGate(ctx, db, remoteName, extraHasRemote, nil)
}

// CheckRemoteMigrateGateForRemoteWithRemoteCheckAndAdopt is
// CheckRemoteMigrateGateForRemoteWithRemoteCheck plus the injected
// fast-forward ancestry callbacks (mybd-ae1i piece 2); see
// CheckRemoteMigrateGateWithAdopt. Server mode uses this form: it already has
// both a configured sync remote and the on-disk remote-check fallback.
func CheckRemoteMigrateGateForRemoteWithRemoteCheckAndAdopt(ctx context.Context, db DBConn, remoteName string, extraHasRemote func() bool, adopt *FastForwardAdopter) error {
	return checkRemoteMigrateGate(ctx, db, remoteName, extraHasRemote, adopt)
}

func checkRemoteMigrateGate(ctx context.Context, db DBConn, remoteName string, extraHasRemote func() bool, adopt *FastForwardAdopter) error {
	// CurrentVersion treats a missing schema_migrations table as version 0, so a
	// brand-new database falls through the current==0 check below — nothing to fork.
	current, err := CurrentVersion(ctx, db)
	if err != nil {
		return fmt.Errorf("remote-migrate gate: read current version: %w", err)
	}
	if current == 0 {
		return nil // fresh database — nothing to fork
	}

	pending, err := PendingVersions(ctx, db)
	if err != nil {
		return fmt.Errorf("remote-migrate gate: read pending versions: %w", err)
	}
	if len(pending) == 0 {
		return nil // already current — nothing to migrate
	}

	hasRemote, err := anyDoltRemoteConfigured(ctx, db)
	if err != nil {
		return fmt.Errorf("remote-migrate gate: read remotes: %w", err)
	}
	// dolt_remotes can read empty even when a remote is configured: a freshly

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error and restore connectivity to the Dolt server.
  2. Check whether schema_migrations is corrupt; restore from Dolt history (`dolt checkout` an earlier commit of the table) if needed.
  3. Verify DB credentials and SELECT permissions after any rotation.
  4. Retry opening the store — the gate re-reads the version each open.
Defensive patterns

Strategy: try-catch

Validate before calling

// check reachability before opening the store
if err := db.PingContext(ctx); err != nil {
    return fmt.Errorf("cannot run remote-migrate gate: %w", err)
}

Type guard

func isVersionReadErr(err error) bool {
    return strings.Contains(err.Error(), "remote-migrate gate: read current version")
}

Try / catch

if err := CheckRemoteMigrateGate(ctx, db, remote, extraHasRemote); err != nil {
    if isVersionReadErr(err) && isTransientDB(err) {
        return CheckRemoteMigrateGate(ctx, db, remote, extraHasRemote) // retry after reconnect
    }
    return err
}

Prevention

When it happens

Trigger: SELECT of the current schema version fails during checkRemoteMigrateGate — Dolt server unreachable, schema_migrations table corrupt/unreadable, context cancelled during store open.

Common situations: `bd` startup against a remote-backed database whose SQL server is down or whose schema_migrations table is damaged; permission problems after a credentials rotation; network partition to the Dolt server.

Related errors


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