gastownhall/beads · error

unstaging ignored migration tables: %w

Error message

unstaging ignored migration tables: %w

What it means

After the ignored-source migrations run, MigrateUp calls unstageIgnoredTables to remove internal dolt_ignore'd staging tables left behind by the migration pass. This error wraps a failure of that unstaging step. The migrations themselves have applied; only cleanup of the ignored staging tables failed, so the database is functional but the pass aborts before dirty-table verification and schema staging.

Source

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

		// 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)
	}
	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 {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped cause (%w) for the exact SQL error from unstageIgnoredTables and address it (lock, permission, or dolt_ignore rule blocking the drop)
  2. Check for other sessions/locks on the staging tables (dolt status / SHOW PROCESSLIST) and clear them, then re-run MigrateUp
  3. Verify the database user has privileges to alter/drop the internal ignored tables
  4. If a dolt_ignore pattern is swallowing the staging tables, adjust the ignore config so migration staging tables are exempt
  5. Re-run MigrateUp once cleanup can succeed; the schema work already applied and only the post-pass steps were skipped

Example fix

// before: restricted DB user cannot drop ignored staging tables
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'bd'@'%';
// after: allow the DDL the migration cleanup needs
GRANT ALL PRIVILEGES ON *.* TO 'bd'@'%';
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: confirm the session can run DDL on ignored/staging tables
if _, err := db.ExecContext(ctx, "SELECT 1 FROM dolt_status LIMIT 1"); err != nil {
    return fmt.Errorf("working set not inspectable: %w", err)
}
// Verify dolt_ignore config will not block internal staging tables
var pat string
if err := db.QueryRowContext(ctx,
    "SELECT pattern FROM dolt_ignore").Scan(&pat); err == nil && pat == "*" {
    return errors.New("dolt_ignore pattern blocks internal staging tables")
}

Try / catch

applied, err := schema.MigrateUp(ctx, db)
if err != nil {
    if strings.Contains(err.Error(), "unstaging ignored migration tables:") {
        cause := errors.Unwrap(err)
        return fmt.Errorf("cleanup failed after migrations applied (%v); inspect ignored staging tables and re-run", cause)
    }
    return err
}

Prevention

When it happens

Trigger: Calling MigrateUp/MigrateUpWithLock when unstageIgnoredTables(ctx, db) returns an error — typically a SQL failure while dropping/altering the dolt_ignore'd staging tables (locked table, DML-on-ignored-table rejection, permissions, or a dropped connection mid-statement).

Common situations: Dolt's dolt_ignore configuration preventing the cleanup DDL from touching ignored tables, a stale advisory lock or other session holding the staging tables, low-level connection failures during long migrations, or permission-restricted database users that cannot alter/drop the internal tables.

Related errors


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