gastownhall/beads · error
checking dirty tables against pending migrations: %w
Error message
checking dirty tables against pending migrations: %w
What it means
This error wraps a failure in pendingMigrationDirtyTables, which cross-checks the set of pre-existing dirty (uncommitted) tables against the tables that pending migrations will alter. The check itself failed (as opposed to finding matches, which returns *DirtyTablesError instead). MigrateUp aborts because it cannot safely decide whether dirty tables would be clobbered.
Source
Thrown at internal/storage/schema/schema.go:637
return 0, fmt.Errorf("reading pre-migration status: %w", err)
}
delete(dirtyBefore, "dolt_ignore")
// A previous pass that crashed mid-aux-rekey left its partial UPDATEs
// dirty in the working set with the in-progress sentinel still recorded
// (bd-578h9.16). Those tables are this pass's own migration state, not
// pre-existing user writes: dropping them from dirtyBefore exempts them
// from the changed-signature guard (the resumed rekey is about to change
// them) and lets stageSchemaTables commit them with the rest of the pass.
if resuming, err := anyAuxRekeyResumePending(ctx, db); err != nil {
return 0, fmt.Errorf("reading aux rekey sentinel: %w", err)
} else if resuming {
for _, t := range auxRekeyTables {
delete(dirtyBefore, t.name)
}
}
touchedDirtyTables, err := mainSource.pendingMigrationDirtyTables(ctx, db, dirtyBefore)
if err != nil {
return 0, fmt.Errorf("checking dirty tables against pending migrations: %w", err)
}
if len(touchedDirtyTables) > 0 {
return 0, &DirtyTablesError{Tables: touchedDirtyTables}
}
dirtyBeforeSignatures, err := dirtyTableSignatures(ctx, db, dirtyBefore)
if err != nil {
return 0, fmt.Errorf("reading pre-migration dirty table diffs: %w", err)
}
// Captured before the main migrations run: the aux re-key uses it to
// distinguish the lineage's first rekey-aware migration (run the pass)
// from a fresh clone of an already-converged lineage (record the marker
// only, bd-578h9.4).
mainVersionBefore, err := mainSource.currentVersion(ctx, db)
if err != nil {
return 0, fmt.Errorf("reading pre-migration schema version: %w", err)
}
applied, mainColumnAdded, err := mainSource.migrate(ctx, db, 0)View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause for the failing query or bad migration metadata
- Fix or remove any migration file whose name lacks a numeric version prefix
- Ensure the database is opened read-write and the engine is healthy, then retry
- If only dirty-table detection is noisy, commit or stash unrelated working-set changes before migrating
Defensive patterns
Strategy: try-catch
Validate before calling
// Commit or verify a clean-enough working set before migrating rows, _ := db.QueryContext(ctx, "SELECT table_name FROM dolt_status WHERE staged=0 AND committed=0") // if suspicious user tables are dirty, resolve them before calling MigrateUp
Type guard
func isDirtyCheckErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "checking dirty tables against pending migrations")
}
var _ = isDirtyCheckErr Try / catch
if _, err := schema.MigrateUp(ctx, db); err != nil {
var dirty *schema.DirtyTablesError
switch {
case errors.As(err, &dirty):
return fmt.Errorf("commit tables %v first", dirty.Tables)
case isDirtyCheckErr(err):
return fmt.Errorf("migration safety check failed: %w", err)
}
return err
} Prevention
- Do not leave hand-modified rows uncommitted in bd tables across upgrades
- Name migration files strictly as <number>_<name> so version parsing never fails
- Run migrations single-threaded under the advisory lock
When it happens
Trigger: Calling MigrateUp/MigrateUpWithLock when pendingMigrationDirtyTables returns an error - typically a Dolt query failure while enumerating pending migrations or dirty table names, or malformed migration metadata (unparseable version names).
Common situations: A migration file with a name that fails parseVersion, database opened read-only while the check attempts reads that fail, or transient embedded-Dolt engine errors during a busy working set.
Related errors
- reading pre-migration dirty table diffs: %w
- checking dirty tables against pending ignored migrations: %w
- pending ignored schema migrations alter pre-existing dirty t
- failed to migrate credential keys: %w
- failed to update encrypted password for peer %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6770337018642c64.
Report an issue: GitHub.