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
- Read the wrapped cause (%w) for the exact SQL error from unstageIgnoredTables and address it (lock, permission, or dolt_ignore rule blocking the drop)
- Check for other sessions/locks on the staging tables (dolt status / SHOW PROCESSLIST) and clear them, then re-run MigrateUp
- Verify the database user has privileges to alter/drop the internal ignored tables
- If a dolt_ignore pattern is swallowing the staging tables, adjust the ignore config so migration staging tables are exempt
- 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
- Do not add broad dolt_ignore patterns (like *) that swallow migration staging tables
- Grant the migration user full DDL privileges on the database
- Run migrations on a stable connection with no competing sessions holding locks on internal tables
- Re-run MigrateUp after transient cleanup failures; the migrations themselves already applied
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
- clearing aux rekey sentinel: %w
- failed to migrate credential keys: %w
- failed to update encrypted password for peer %s: %w
- failed to initialize schema: %w
- failed to rebuild pool after migration: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/951a7a53028632b6.
Report an issue: GitHub.