gastownhall/beads · critical

dolt commit after SQL mutation: %w: %w

Error message

dolt commit after SQL mutation: %w: %w

What it means

CALL DOLT_COMMIT failed after staging tables following a SQL mutation. Wrapped with ErrCommitIndeterminate because the mutation already succeeded — the commit may or may not have landed, so it must not be replayed blindly. 'nothing to commit' responses are intentionally tolerated and not an error.

Source

Thrown at internal/storage/dolt/store.go:3320

		// Skip the commit when nothing was actually staged (idempotent no-op
		// write), so Dolt does not log a server-side "nothing to commit" warning
		// on every reconcile-cadence call. The guard tests the STAGED set rather
		// than the whole working set because this helper stages only a fixed
		// table list — an unrelated dirty table must not trigger an empty '-m'
		// commit. A guard-read failure is NOT a publication failure: nothing has
		// been committed and nothing is indeterminate, so plain error return.
		staged, err := issueops.HasStagedChanges(ctx, conn)
		if err != nil {
			return fmt.Errorf("check staged changes before commit: %w", err)
		}
		if !staged {
			return nil
		}

		if err := schema.DrainCall(ctx, conn, "CALL DOLT_COMMIT('-m', ?, '--author', ?)",
			commitMsg, s.commitAuthorString()); err != nil && !isDoltNothingToCommit(err) {
			return s.recordDoltPublicationFailure(ctx,
				fmt.Errorf("dolt commit after SQL mutation: %w: %w", err, ErrCommitIndeterminate))
		}
		return nil
	})
}

func (s *DoltStore) wrapDoltPublicationFailure(ctx context.Context, op string, err error) error {
	return s.recordDoltPublicationFailure(ctx, wrapSQLCommitError(op, err))
}

// recordDoltPublicationFailure accounts once for an ambiguous connection loss
// at a Dolt publication boundary. Direct publication helpers stay outside
// withRetryTx; transaction-backed writes call this from withRetryTx itself.
func (s *DoltStore) recordDoltPublicationFailure(ctx context.Context, err error) error {
	if s.breaker == nil || !errors.Is(err, ErrCommitIndeterminate) || !isConnectionError(err) {
		return err
	}
	s.breaker.RecordFailure()
	if s.breaker.State() == circuitOpen {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check `bd dolt log` / `bd dolt status` to determine whether the commit landed before doing anything else.
  2. If it landed, no action needed. If not and the working set is intact, re-run the operation to publish.
  3. Resolve any conflicts shown by dolt status, then re-commit.
  4. Record/review server logs for the failure cause.
Defensive patterns

Strategy: try-catch

Validate before calling

// before re-running: did the commit land?
out, _ := exec.Command("bd", "dolt", "log", "-n", "1", "--json").Output()
// compare HEAD message/author against the intended commitMsg before retrying

Try / catch

if errors.Is(err, ErrCommitIndeterminate) {
    // check `bd dolt log` / `bd dolt status`: commit may have landed
    // do NOT replay the mutation/commit blindly
}

Prevention

When it happens

Trigger: doltAddAndCommit staged the tables (guard saw staged changes) and DOLT_COMMIT('-m', ...) returns a real error — server drop, merge conflict, or commit hook failure.

Common situations: Dolt server crash between add and commit; another writer committed conflicting changes creating a conflict; network partition to a server-mode Dolt.

Related errors


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