gastownhall/beads · error
schema behind-drift check: %w
Error message
schema behind-drift check: %w
What it means
This error wraps a failure to read `MAX(version)` from `schema_migrations` during the behind-drift check. CheckBehindDrift runs on read-only open paths that cannot migrate; this wrapper means the drift check itself failed because the schema_migrations table could not be queried, not that the DB is behind.
Source
Thrown at internal/storage/schema/schema.go:198
// *SchemaBehindError.
func IsSchemaBehindError(err error) bool {
var e *SchemaBehindError
return errors.As(err, &e)
}
// CheckBehindDrift returns a *SchemaBehindError when the database's schema
// version is behind the binary's. Used by read-only opens, which skip
// MigrateUp by design (bd-6dnrw.32) — the paths that previously auto-migrated
// foreign databases (GH#3231) now need a clear open-time failure instead of
// unknown-column errors at query time. BD_IGNORE_SCHEMA_SKEW=1 downgrades it
// to a warning, mirroring forward drift. A fresh DB (version 0) is reported
// as behind too: it has no readable schema at all.
func CheckBehindDrift(ctx context.Context, db *sql.DB) error {
var currentVersion int
if err := db.QueryRowContext(ctx,
"SELECT COALESCE(MAX(version), 0) FROM schema_migrations",
).Scan(¤tVersion); err != nil {
return fmt.Errorf("schema behind-drift check: %w", err)
}
if currentVersion >= LatestVersion() {
return nil
}
if os.Getenv("BD_IGNORE_SCHEMA_SKEW") == "1" {
fmt.Fprintf(os.Stderr,
"Warning: schema skew ignored — database (v%d) is behind binary (v%d) and was opened read-only; some queries may fail\n",
currentVersion, LatestVersion())
return nil
}
return &SchemaBehindError{DBVersion: currentVersion, BinaryVersion: LatestVersion()}
}
type dirtyTableState struct {
staged bool
}
var doltStatusTableNameRE = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`)View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause to identify the underlying query failure
- Confirm the Dolt server is reachable and the repo's working set is clean (`dolt status`)
- Wait for any concurrent migration process to finish, then retry
- Restore from backup if schema_migrations is corrupt
Defensive patterns
Strategy: try-catch
Validate before calling
var v int
if err := db.QueryRowContext(ctx, "SELECT COALESCE(MAX(version),0) FROM schema_migrations").Scan(&v); err != nil {
return err // cannot even evaluate behind-drift
} Type guard
func isBehindDriftCheckFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "behind-drift check:")
} Try / catch
if err := CheckBehindDrift(ctx, db); err != nil {
if schema.IsSchemaBehindError(err) {
// run a write command once to migrate
} else {
// query failed: server/lock/corruption issue
return err
}
} Prevention
- Never open the same workspace read-only while another process migrates it
- Run migrations before switching to read-only access paths
- Verify `dolt status` is clean before read-only opens
When it happens
Trigger: Calling CheckBehindDrift on a database where the `schema_migrations` SELECT fails: table missing/corrupt, connection error, context cancellation, or a Dolt working-set lock held by another process.
Common situations: Read-only open against a workspace mid-migration by another process; corrupted repo; Dolt server unavailable; networked Dolt with a dropped connection.
Related errors
- schema skew check: %w
- clone from %s succeeded, but the database needs %d schema %s
- legacy SQLite release marker: %w
- legacy SQLite schema drift in %s hidden column
- legacy SQLite schema drift in %s
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ba2d7ccd63480120.
Report an issue: GitHub.