gastownhall/beads · critical

acquire connection after SQL mutation: %w: %w

Error message

acquire connection after SQL mutation: %w: %w

What it means

In commitWorkingSetAfterSQLCommit, acquiring a connection after a SQL mutation failed. Because a mutation already succeeded but the commit did not run, the error is wrapped with ErrCommitIndeterminate — the commit outcome is unknown and must not be blindly retried.

Source

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

}

// doltAddAndCommit stages the specified tables and commits on a pinned
// connection. This prevents DOLT_COMMIT('-Am') from sweeping up stale
// working set changes from concurrent operations (GH#2455). Every caller has
// already committed its SQL mutation, so any publication failure here has an
// indeterminate durable outcome and must not be replayed.
func (s *DoltStore) doltAddAndCommit(ctx context.Context, tables []string, commitMsg string) error {
	// Batch/off auto-commit (bd-4wamg): leave the writes in the working set
	// for a later explicit commit point (bd dolt commit / CommitPending),
	// matching doltAddAndCommitInTx.
	if issueops.VersionCommitDeferred(ctx) {
		return nil
	}
	return s.withCircuitWrite(ctx, func(ctx context.Context) error {
		conn, err := s.db.Conn(ctx)
		if err != nil {
			return s.recordDoltPublicationFailure(ctx,
				fmt.Errorf("acquire connection after SQL mutation: %w: %w", err, ErrCommitIndeterminate))
		}
		defer conn.Close()

		for _, table := range tables {
			if err := schema.DrainCall(ctx, conn, "CALL DOLT_ADD(?)", table); err != nil {
				return s.recordDoltPublicationFailure(ctx,
					fmt.Errorf("dolt add %s after SQL mutation: %w: %w", table, err, ErrCommitIndeterminate))
			}
		}

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

View on GitHub (pinned to 71377f2769)

Solutions

  1. Treat the commit as indeterminate: run `bd dolt status` / `bd dolt log` to check whether the commit landed before retrying.
  2. Restore Dolt server connectivity, then re-run the operation; the code path is idempotent for uncommitted staged changes.
  3. If the commit did land, do nothing further; if not, re-trigger the operation to publish.
  4. Check server logs for crash/restart at that timestamp.
Defensive patterns

Strategy: try-catch

Validate before calling

// check server reachability before mutations that require publication
if err := s.db.PingContext(ctx); err != nil {
    return fmt.Errorf("skip mutation: publication path unavailable: %w", err)
}

Try / catch

if errors.Is(err, ErrCommitIndeterminate) {
    // verify with `bd dolt log` / `bd dolt status` whether the commit landed
    // before re-triggering the operation
}

Prevention

When it happens

Trigger: The store attempts to dolt-add/commit tables after a raw SQL mutation (doltAddAndCommit path) and s.db.Conn(ctx) fails because the server became unreachable or the pool drained at exactly that moment.

Common situations: Dolt server crash or network drop between the SQL write and the publication commit; connection-pool exhaustion under heavy concurrent agent load.

Related errors


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