gastownhall/beads · error
reading pre-migration dirty table diffs: %w
Error message
reading pre-migration dirty table diffs: %w
What it means
This error wraps a failure in dirtyTableSignatures, which captures pre-migration diffs (signatures) of dirty tables so MigrateUp can later prove those tables were not modified by the migration pass. If signatures cannot be read, the safety contract of #4566 (clean working set after an interrupted pass) cannot be enforced, so the migration aborts before applying anything.
Source
Thrown at internal/storage/schema/schema.go:644
// 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)
if err != nil {
return applied, err
}
backfilled, err := ensureBackfilledCustomStatusesCustomTypes(ctx, db)
if err != nil {
return applied, fmt.Errorf("backfill custom tables: %w", err)View on GitHub (pinned to 71377f2769)
Solutions
- Resolve the wrapped cause (failing diff/status query) shown after this message
- Stop concurrent writers to the repository before running migrations
- Commit or revert pre-existing working-set changes so there are no dirty tables to signature
- Restore the table or database from a Dolt commit if diff data is corrupt
Defensive patterns
Strategy: retry
Validate before calling
// Ensure no concurrent writers before migrating
if locked, _ := tryLock(ctx, db); !locked {
return errors.New("another writer holds the migration lock")
} Type guard
func isSignatureReadErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "reading pre-migration dirty table diffs")
} Try / catch
applied, err := schema.MigrateUp(ctx, db)
if isSignatureReadErr(err) {
// transient diff-read failure: safe to retry, nothing was applied yet
return retryMigrateUp(ctx, db)
} Prevention
- Use MigrateUpWithLock to serialize against other writers
- Avoid long-lived open transactions on the same repo during bd open
- Keep Dolt diff history healthy (regular commits, no forced truncation)
When it happens
Trigger: Calling MigrateUp/MigrateUpWithLock when dirtyTableSignatures errors - e.g. dolt_diff/status queries on one of the pre-existing dirty tables fail, or a dirty table was dropped/renamed between the status read and this call.
Common situations: Concurrent writers mutating the working set between the two pre-flight reads; corrupt diff history on a dirty table; a table listed dirty earlier but now inaccessible.
Related errors
- checking dirty tables against pending migrations: %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/c356c838b4fd6268.
Report an issue: GitHub.