gastownhall/beads · error
failed to begin transaction: %w
Error message
failed to begin transaction: %w
What it means
execWithLongTimeout begins a transaction on the dedicated long-timeout connection to run a long query (e.g. fetch/pull). This error wraps tx.BeginTx failure — the driver could not get a connection or start a transaction within the context deadline.
Source
Thrown at internal/storage/dolt/store.go:2251
// falls back to the remote's configured refspecs (ParseRefSpecs ->
// GetRefSpecs), which are remote config rather than session state, and a
// fetch writes only remote-tracking refs, never the working branch. Neither
// depends on this fresh connection's default checkout.
func (s *DoltStore) execWithLongTimeout(ctx context.Context, query string, args ...any) error {
cfg, err := mysql.ParseDSN(s.connStr)
if err != nil {
return fmt.Errorf("failed to parse DSN for long-timeout connection: %w", err)
}
cfg.ReadTimeout = 5 * time.Minute
db, err := sql.Open("mysql", cfg.FormatDSN())
if err != nil {
return fmt.Errorf("failed to open long-timeout connection: %w", err)
}
defer db.Close()
db.SetMaxOpenConns(1)
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
if _, err := tx.ExecContext(ctx, query, args...); err != nil {
_ = tx.Rollback()
return err
}
return tx.Commit()
}
// execWithLongTimeoutNoTx executes a long-running Dolt stored procedure without
// an explicit transaction. Push operations do not need the pull/merge conflict
// handling above, and DOLT_PUSH has diverged from direct `dolt push` behavior
// when wrapped in a SQL transaction.
//
// Audited for be-b0am's fresh-connection branch hazard: safe. Every caller
// passes s.branch explicitly as a CALL DOLT_PUSH(...) arg, so this fresh
// connection's default checkout never matters.
func (s *DoltStore) execWithLongTimeoutNoTx(ctx context.Context, query string, args ...any) error {
db, err := s.oneShotConn(5 * time.Minute)View on GitHub (pinned to 71377f2769)
Solutions
- Check server reachability (bd dolt status, ping host:port)
- Verify credentials and DSN host/port
- Retry with a fresh context if the parent deadline expired
- Check server logs for connection limits or auth errors
Example fix
// before ctx := context.Background() err := store.execWithLongTimeout(ctx, query) // hangs then fails confusingly // after ctx, cancel := context.WithTimeout(context.Background(), 6*time.Minute) defer cancel() err := store.execWithLongTimeout(ctx, query)
Defensive patterns
Strategy: retry
Validate before calling
if err := db.PingContext(ctx); err != nil {
return fmt.Errorf("cannot reach server before long query: %w", err)
}
if ctx.Err() != nil { return ctx.Err() } Try / catch
err := store.execWithLongTimeout(ctx, q)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || isConnRefused(err) {
// check server, retry with fresh long context
}
return err
} Prevention
- Give long ops a context budget exceeding ReadTimeout
- Monitor Dolt server liveness before big fetches
- Verify auth and port in config
- Handle server restarts with reconnect logic
When it happens
Trigger: Calling execWithLongTimeout when db.BeginTx(ctx, nil) fails — pool cannot establish a connection (server down, port wrong, auth rejected) or ctx already cancelled/timed out.
Common situations: Dolt server stopped or restarted; wrong port/host in config; credentials rejected; long-past context deadline from a parent operation.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f61aad649ed035cc.
Report an issue: GitHub.