gastownhall/beads · error

committing migrations: %w

Error message

committing migrations: %w

What it means

This error wraps a failure from `CALL DOLT_COMMIT('-m', 'schema: apply migrations')` at the end of MigrateUp. After schema migrations have applied and staged changes were detected (stageSchemaTables returned true), the library attempts to commit the migration work so the database converges to a clean working set. If Dolt rejects the commit for any reason other than "nothing to commit" (which is tolerated and swallowed), the underlying driver error is wrapped as "committing migrations: %w".

Source

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

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

	return applied, nil
}

func migrationWorkNeeded(ctx context.Context, db DBConn) (bool, error) {
	if !mainSource.atLatest(ctx, db) || !ignoredSource.atLatest(ctx, db) {
		return true, nil
	}
	// A database already at the latest numbered migration still needs work if it
	// predates the content_hash column (gastownhall/beads#4259 reporter fix No.2).
	// Without this, MigrateUp short-circuits before migrate() runs the idempotent
	// ALTER, so the recording/detection surface is never installed on exactly the
	// already-upgraded databases the fix is meant to protect.
	hasMainHash, err := mainSource.hasContentHashColumn(ctx, db)
	if err != nil {
		return false, err

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped cause (%w) printed after "committing migrations:" — it names the actual Dolt failure; fix that condition first.
  2. Run `bd doctor` (or `dolt status` in the .beads database dir) to check for a dirty/conflicting working set, then resolve or reset the conflicted tables.
  3. Retry the open/migration after ensuring the database directory is writable and no other process holds the DB lock (MigrateUpWithLock takes the advisory lock for you).
  4. If the working set is corrupted by a crashed pass, verify the migration self-heal path: re-run MigrateUp — the #4566 contract expects a retry from a clean working set to converge.
  5. Check the installed Dolt/embedded-dolt version against the version beads was built for; upgrade or downgrade to a compatible release.

Example fix

// before: opaque failure at open time
if err := DrainCall(ctx, db, "CALL DOLT_COMMIT('-m', 'schema: apply migrations')"); err != nil {
    return applied, fmt.Errorf("committing migrations: %w", err)
}
// after: caller-side handling that inspects the cause and retries once
var openErr error
for i := 0; i < 2; i++ {
    _, openErr = storage.Open(ctx, dbPath)
    if openErr == nil || !strings.Contains(openErr.Error(), "committing migrations") {
        break
    }
    time.Sleep(500 * time.Millisecond) // transient engine/lock condition
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: ensure the database dir is writable and no merge state before migrating
func canCommit(dbPath string) error {
    fi, err := os.Stat(dbPath)
    if err != nil || !fi.IsDir() {
        return fmt.Errorf("db path missing: %s", dbPath)
    }
    if err := unix.Access(dbPath, unix.W_OK); err != nil {
        return fmt.Errorf("db not writable: %w", err)
    }
    return nil
}

Type guard

// Go: the wrapped error is opaque (%w of a driver error); narrow by message
func isMigrationCommitError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "committing migrations:")
}

Try / catch

_, err := schema.MigrateUp(ctx, db)
if err != nil {
    var pathErr *os.PathError
    switch {
    case isMigrationCommitError(err):
        // inspect wrapped cause, check `dolt status`, retry once
    case errors.As(err, &pathErr):
        // fix filesystem permission
    default:
        return err
    }
}

Prevention

When it happens

Trigger: Calling MigrateUp (directly or via MigrateUpWithLock) when stageSchemaTables staged migration changes but the subsequent DOLT_COMMIT fails — e.g. Dolt server refused the commit, a merge/conflict state exists, the DB is read-only, or the connection dropped mid-commit. Only non-"nothing to commit" errors produce this.

Common situations: Running `bd` against an embedded Dolt database whose working set entered a conflicting state between staging and commit; opening a database on a read-only filesystem; an interrupted earlier migration pass leaving the repo in a state Dolt refuses to commit; Dolt version differences changing DOLT_COMMIT behavior; transient connection loss to the storage engine.

Related errors


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