gastownhall/beads · error
failed to stage %s before commit: %w
Error message
failed to stage %s before commit: %w
What it means
Once dirty tables are discovered, each is staged with CALL DOLT_ADD(?) via schema.DrainCall before DOLT_COMMIT runs. This error wraps a failure of that stored-procedure call for a specific table (the %s names it). The commit did not complete; the failure happened mid-staging, so the Dolt working set may have some tables staged.
Source
Thrown at internal/storage/dolt/store.go:3114
}
if len(tables) == 0 {
// A merge resolution with a clean working set is NOT a no-op: it is
// the `--ours` case, where our values already stood and resolving the
// conflict dirtied nothing. Returning here left is_merging true while
// the caller reported "Merge committed", and the next pull re-wedged
// on the unconcluded merge (wy-36ilm, caught by the F9 integration
// test). Only the merge-conclusion mode takes this path: for the
// other modes an empty working set really is nothing to commit.
if mode == configIncludeAll {
return s.concludeOpenMerge(ctx, conn, message)
}
return nil // Nothing to commit (all changes were config-only or dolt_ignore'd)
}
for _, table := range tables {
if err := schema.DrainCall(ctx, conn, "CALL DOLT_ADD(?)", table); err != nil {
return fmt.Errorf("failed to stage %s before commit: %w", table, err)
}
}
// NOTE: In SQL procedure mode, Dolt defaults author to the authenticated SQL user
// (e.g. root@localhost). Always pass an explicit author for deterministic history.
if err := schema.DrainCall(ctx, conn, "CALL DOLT_COMMIT('-m', ?, '--author', ?)", message, s.commitAuthorString()); err != nil {
if isDoltNothingToCommit(err) {
return nil
}
return s.wrapDoltPublicationFailure(ctx, "failed to commit", err)
}
return nil
}
// commitWorkingSetAfterSQLCommit preserves the no-replay boundary for a Dolt
// publication that follows an already-visible SQL mutation. commitWorkingSet
// classifies DOLT_COMMIT response loss itself; this wrapper adds the sameView on GitHub (pinned to 71377f2769)
Solutions
- Re-run the commit; dolt_status is re-queried so the stale table drops out of the staging list.
- Check for concurrent bd processes/sync jobs operating on the same repo and serialize them (file lock or single writer).
- Verify the named table still exists (SHOW TABLES) and is not blocked by a dolt_ignore rule.
- If DOLT_ADD keeps failing, inspect Dolt session state (dolt_status in a SQL shell) and retry on a fresh connection.
Defensive patterns
Strategy: retry
Validate before calling
// confirm the repo is quiescent before committing // e.g. acquire your own single-writer lock; verify table exists: // SHOW TABLES LIKE '<table>'
Try / catch
err := store.Commit(ctx, msg)
if err != nil && strings.Contains(err.Error(), "failed to stage") {
// safe to re-run: dolt_status is re-queried next attempt
time.Sleep(time.Second); return store.Commit(ctx, msg)
} Prevention
- Prevent concurrent bd writers on the same repo (single-writer lock or one sync job).
- Re-run the commit after races — staging restarts cleanly.
- Avoid schema changes (drop/rename) while a commit is in flight.
- Review dolt_ignore rules if a target table is being skipped.
When it happens
Trigger: DOLT_ADD fails for one table: the table was dropped/renamed between discovery and staging, a dolt_ignore rule conflicts, the session hit an error from a prior call, or the procedure returned an error row that DrainCall surfaces.
Common situations: Concurrent operations (another bd process committing/checking out) changing table presence mid-commit; GH#2455-style races with stale config rows; schema migrations removing tables while a commit is in flight.
Related errors
- failed to commit restore: %w
- failed to stage is_blocked repairs: %w
- failed to commit orphaned dependency removals: %w
- failed to commit federation peer: %w
- publish working set after SQL commit: %w: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c32fb86feb27590f.
Report an issue: GitHub.