gastownhall/beads · error

checking dirty tables against pending ignored migrations: %w

Error message

checking dirty tables against pending ignored migrations: %w

What it means

This error wraps a failure in ignoredSource.pendingMigrationDirtyTables - the mid-pass re-check of whether pending ignored-source migrations would alter pre-existing dirty tables. Unlike a positive finding (which yields the plain table-list error at 4009), this is the check itself erroring out, after main migrations already applied.

Source

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

	// migration 0037 randomized per-clone, the same hazard class on the aux
	// tables. Gated on the clone-local ignored marker (recorded later in this
	// pass by ignoredSource.migrate) so it runs exactly once per clone instead
	// of churning synced rows on every later migration pass — and on the
	// pre-pass main cursor, so fresh clones of converged lineages record the
	// marker without re-running the rewrite (bd-578h9.4).
	// ...and the bd-ri8bd sibling: one more pass over the same tables for the
	// rows minted with random UUIDv7 ids between the initial backfill and the
	// switch to content-derived ids at insert time. Same machinery, own
	// marker/sentinel/shipped-version gates, one shared cursor read.
	auxRekeyed, err := rekeyAuxRowIDsAllPasses(ctx, db, mainVersionBefore)
	if err != nil {
		return applied, fmt.Errorf("rekey aux row ids: %w", err)
	}
	backfilled = backfilled || auxRekeyed

	touchedIgnoredDirtyTables, err := ignoredSource.pendingMigrationDirtyTables(ctx, db, dirtyBeforeAll)
	if err != nil {
		return applied, fmt.Errorf("checking dirty tables against pending ignored migrations: %w", err)
	}
	if len(touchedIgnoredDirtyTables) > 0 {
		// Deliberately a plain, untyped error (unlike the main-source guard
		// above, which returns *DirtyTablesError): this check fires mid-pass,
		// after the main-source migrations have already applied. A lenient
		// caller (embeddeddolt's openReadOnlyCommand / openWorkingSetReconcile
		// intents) skipping this and returning as if the open succeeded would
		// let a reconcile commit checkpoint a half-applied migration pass.
		// The ignored source also tracks bd-internal state (dolt_ignore'd
		// tables like ignored_schema_migrations), not expected user data, so
		// 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)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped cause for the failing ignored-source query
  2. Repair or restore ignored_schema_migrations / dolt_ignore'd internal tables from a healthy clone
  3. Eliminate concurrent writers for the duration of MigrateUp
  4. Re-run MigrateUp once the internal tables are readable
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure internal ignored tables are queryable before opening
if _, err := db.QueryContext(ctx, "SELECT 1 FROM ignored_schema_migrations LIMIT 1"); err != nil {
    return fmt.Errorf("internal migration tables unreadable: %w", err)
}

Type guard

func isIgnoredDirtyCheckErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "checking dirty tables against pending ignored migrations")
}

Try / catch

applied, err := schema.MigrateUp(ctx, db)
if isIgnoredDirtyCheckErr(err) {
    return fmt.Errorf("mid-pass check failed after %d main migrations: %w", applied, err)
}

Prevention

When it happens

Trigger: Calling MigrateUp/MigrateUpWithLock where the ignored-source dirty-table cross-check fails - Dolt query errors against dolt_ignore'd internal tables (ignored_schema_migrations), malformed ignored migration metadata, or engine errors mid-pass.

Common situations: Databases where the ignored source's tables were damaged or copied incompletely; concurrent writers invalidating the earlier dirty snapshot mid-pass; read-only opens that fail on internal writes.

Related errors


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