gastownhall/beads · error
checking schema migration work: %w
Error message
checking schema migration work: %w
What it means
This error means the 'already converged' fast-path check could not determine whether schema migrations are needed because migrationWorkNeeded itself returned an error (cursor probe, content-hash column probe, or backfill-need probe all failed). The fast path is exactly MigrateUp's own gate and runs first, so this typically indicates a fresh or mid-upgrade database with missing tables, or an unhealthy connection. It aborts the fast path; the locked MigrateUp path should still run.
Source
Thrown at internal/storage/schema/converged.go:58
// CLI open in uow.openAndInitSchema — pins its schema-init pool with an
// EMPTY DSN database and only USEs the database after GET_LOCK, so a probe
// that merely ASKED whether the session was already on databaseName read
// NULL from DATABASE() and declined on every single invocation: the fast
// path never fired where it was needed.
onTarget, qualifier, err := selectTargetDatabase(ctx, db, databaseName, selector)
if err != nil {
return false, err
}
if !onTarget {
return false, nil
}
// Exactly MigrateUp's own gate, and it runs first: on a fresh or
// mid-upgrade database it reports work needed from the cursor probe alone,
// before any statement that could fail against a missing table.
needed, err := migrationWorkNeeded(ctx, db)
if err != nil {
return false, fmt.Errorf("checking schema migration work: %w", err)
}
if needed {
return false, nil
}
// MigrateUp re-asserts the canonical dolt_ignore patterns ahead of that
// gate precisely because an out-of-band-materialized database can arrive
// with its cursors at-latest and the patterns missing. Read the same
// question instead of writing it: an under-seeded database is not
// converged and must take the locked path, which heals and commits it.
//
// migrationWorkNeeded has just proved mainSource.atLatest, i.e. the main
// cursor is at or past mainSource.latest(); every version-gated pattern's
// flip migration is part of that embedded set, so the gate can be
// evaluated against latest() with no second cursor read.
seeded, err := doltIgnoreSeeded(ctx, db, qualifier, mainSource.latest())
if err != nil {
return false, errView on GitHub (pinned to 71377f2769)
Solutions
- Run the normal locked MigrateUp path — on a fresh DB this fast-path failure is bypassed by full migration; ensure MigrateUp executes.
- Check Dolt server availability and reconnect.
- Verify the DB user can read information_schema and the schema tables.
- If it persists on an existing DB, read the wrapped cause to find which sub-probe failed and repair that table/schema.
Example fix
// before: abort everything when the fast-path probe fails
needed, err := migrationWorkNeeded(ctx, db)
if err != nil {
return false, fmt.Errorf("checking schema migration work: %w", err)
}
// after: fall through to the locked migrate path on a missing-table probe failure
needed, err := migrationWorkNeeded(ctx, db)
if err != nil && !isMissingTableErr(err) {
return false, fmt.Errorf("checking schema migration work: %w", err)
}
if err != nil || needed {
return false, nil // fall through to full migration
} Defensive patterns
Strategy: fallback
Validate before calling
// Determine freshness before trusting fast-path probes var tables int db.QueryRowContext(ctx, `SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()`).Scan(&tables) fresh := tables == 0
Try / catch
converged, err := checkConverged(ctx, db)
if err != nil {
// fast path could not evaluate — fall back to the locked full-migrate path
converged = false
err = migrateUpWithLock(ctx, db)
} Prevention
- Always have a full-migration fallback when short-circuit probes fail
- Validate DB connectivity before migration checks
- Run under a DB user with information_schema access
- Treat 'missing table' errors on fresh databases as a normal state, not a fatal one
When it happens
Trigger: alreadyConverged (used by MigrateUpWithLock) calls migrationWorkNeeded, whose atLatest probes or needsBackfilledCustomStatusesCustomTypes hit a SQL error — missing schema tables on a fresh DB, information_schema failure, connection loss, or cancelled context.
Common situations: Opening a brand-new database before any migration ran; connection to the Dolt server dropped at startup; restricted DB user lacking information_schema access; schema damage from an interrupted earlier migration.
Related errors
- failed to initialize schema: %w
- counting unbackfilled dependencies.id rows for migration 005
- ignored migrations: %w
- migration %s: %w
- uow: database %q is at schema v%d, this bd expects v%d; the
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b13c860a983e5059.
Report an issue: GitHub.