gastownhall/beads · error

checking pre-existing dirty table diffs: %w

Error message

checking pre-existing dirty table diffs: %w

What it means

After all migrations and backfills apply, MigrateUp compares signatures of pre-existing dirty tables against snapshots taken before the pass (changedDirtyTableSignatures) to prove the migration never mutated user data in dirty tables. This error wraps a failure of that comparison query itself — it is a diagnostic failure, not evidence of data change. MigrateUp aborts before staging/committing so a broken verification never lets an unverifiable pass be checkpointed.

Source

Thrown at internal/storage/schema/schema.go:724

		// there is no dirty-commit recovery story to support here the way
		// there is for the main-source guard (#4566 scope).
		return applied, fmt.Errorf("pending ignored schema migrations alter pre-existing dirty tables: %s", strings.Join(touchedIgnoredDirtyTables, ", "))
	}

	appliedIgnored, ignoredColumnAdded, err := ignoredSource.migrate(ctx, db, 0)
	if err != nil {
		return applied, fmt.Errorf("ignored migrations: %w", err)
	}
	if err := unstageIgnoredTables(ctx, db); err != nil {
		return applied, fmt.Errorf("unstaging ignored migration tables: %w", err)
	}

	if applied == 0 && !backfilled && appliedIgnored == 0 && !mainColumnAdded && !ignoredColumnAdded {
		return applied, nil
	}
	changedDirtyTables, err := changedDirtyTableSignatures(ctx, db, dirtyBeforeSignatures)
	if err != nil {
		return applied, fmt.Errorf("checking pre-existing dirty table diffs: %w", err)
	}
	if len(changedDirtyTables) > 0 {
		return applied, fmt.Errorf("pre-existing dirty tables changed during schema migration: %s", strings.Join(changedDirtyTables, ", "))
	}

	staged, err := stageSchemaTables(ctx, db, dirtyBefore)
	if err != nil {
		return applied, fmt.Errorf("staging migrations: %w", err)
	}
	if !staged {
		return applied, nil
	}
	if err := DrainCall(ctx, db, "CALL DOLT_COMMIT('-m', 'schema: apply migrations')"); err != nil {
		if !strings.Contains(strings.ToLower(err.Error()), "nothing to commit") {
			return applied, fmt.Errorf("committing migrations: %w", err)
		}
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped cause (%w) for the failing introspection query and fix the underlying SQL/driver error
  2. Ensure no concurrent process is altering or dropping tables during migration — run MigrateUp under the advisory lock (MigrateUpWithLock) and stop competing writers, then re-run
  3. Verify the database connection is stable (no mid-pass disconnects) and re-run on a healthy connection
  4. If a dirty table's metadata is unreadable/corrupt, repair or restore that table before migrating again
  5. Re-run MigrateUp after fixing; migrations already applied, only verification and staging were skipped

Example fix

// before: migrating without a lock while another writer drops tables
_, err := schema.MigrateUp(ctx, db)
// after: take the advisory lock so no concurrent DDL races the diff check
_, err := schema.MigrateUpWithLock(ctx, db)
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: stable connection and no concurrent DDL expected
if err := db.PingContext(ctx); err != nil {
    return fmt.Errorf("unstable connection before migrate: %w", err)
}
// Check for dirty tables whose state the diff check will read
// (MigrateUp itself guards against dirty tables; verify lock availability)
// Prefer the locked entry point:
// applied, err := schema.MigrateUpWithLock(ctx, db)

Try / catch

applied, err := schema.MigrateUpWithLock(ctx, db)
if err != nil {
    if strings.Contains(err.Error(), "checking pre-existing dirty table diffs:") {
        cause := errors.Unwrap(err)
        return fmt.Errorf("migration diff verification failed (%v); migrations applied but not staged/committed — fix and re-run", cause)
    }
    return err
}

Prevention

When it happens

Trigger: Calling MigrateUp/MigrateUpWithLock when changedDirtyTableSignatures(ctx, db, dirtyBeforeSignatures) errors — e.g. the dirty-table signature query fails because a dirty table was dropped/renamed mid-pass, a SQL/driver error occurs while reading table signatures, or the connection fails during the check.

Common situations: Another process mutating schema (dropping tables) while MigrateUp runs, corrupted table metadata that the signature query cannot read, connection timeouts on large databases between the pre- and post-pass reads, or driver-level SQL errors in the signature introspection queries.

Related errors


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