gastownhall/beads · error
checkout active branch %q: %w
Error message
checkout active branch %q: %w
What it means
pinStoreBranch keeps each connection pinned to the store's active branch: it reads active_branch() and issues CALL DOLT_CHECKOUT on the target connection. If that checkout fails (e.g. the branch name no longer exists or the connection's session is in a bad state), the error is wrapped with the branch name so you know which branch could not be selected.
Source
Thrown at internal/storage/dolt/store.go:1071
// pool behind s.db is effectively single-connection. Checkout() leases one
// connection from that pool (s.db.Conn), runs DOLT_CHECKOUT on it and returns
// it — the branch stays with that physical connection, because checkout is
// per-connection session state. The pool defaults to defaultMaxOpenConns (10,
// overridable by BEADS_DOLT_MAX_CONNS or dolt.max-conns), so on a genuinely
// multi-connection pool this read may be served by a sibling connection that
// never saw that checkout and still reports the branch it was opened with.
// The paths that rely on this pin run effectively single-connection —
// server-mode stores are pinned to MaxOpenConns=1 precisely because branch
// isolation is session-level (see iter_issues.go) — so the read is reliable
// in practice rather than by construction. The s.branch fallback does not
// close the gap either: it fires only when the query errors, not when it
// succeeds with another connection's answer.
func (s *DoltStore) pinStoreBranch(ctx context.Context, conn execer) error {
var branch string
if scanErr := s.db.QueryRowContext(ctx, "SELECT active_branch()").Scan(&branch); scanErr == nil {
if branch != "" {
if _, err := conn.ExecContext(ctx, "CALL DOLT_CHECKOUT(?)", branch); err != nil {
return fmt.Errorf("checkout active branch %q: %w", branch, err)
}
}
} else if s.branch != "" {
// Fall back to the store's recorded branch rather than failing the
// whole call outright.
if _, err := conn.ExecContext(ctx, "CALL DOLT_CHECKOUT(?)", s.branch); err != nil {
return fmt.Errorf("checkout fallback branch %q: %w", s.branch, err)
}
}
return nil
}
// withReadTxLongTimeout is like withReadTx but runs fn against a dedicated
// one-shot connection with a 5-minute read timeout (see openLongTimeoutConn)
// instead of the shared pool's 10s ReadTimeout (see buildServerDSN). Use for
// read queries that are known to legitimately run long, e.g. dolt_history_*
// system-table scans on issues with many revisions — the pooled 10s client
// timeout otherwise surfaces as an intermittent MySQL i/o timeout / invalidView on GitHub (pinned to 71377f2769)
Solutions
- Verify the branch exists: run SELECT active_branch() and DOLT_BRANCH() in the database, or bd doctor.
- Recreate the missing branch or reconfigure the store's branch to an existing one.
- Restart the store/process to reset pooled connections if a session is wedged.
- Check whether another process is rewriting branches concurrently and serialize those operations.
Example fix
// before
s.branch = "work/foo" // branch later deleted by another process
// after
// ensure branch exists before opening the store
_, err := db.Exec("CALL DOLT_BRANCH(?, ?)", "work/foo", "main")
s.branch = "work/foo" Defensive patterns
Strategy: fallback
Validate before calling
var branch string
if err := db.QueryRowContext(ctx, "SELECT active_branch()").Scan(&branch); err != nil || branch == "" {
// branch unknown; verify DOLT_BRANCH() list before writing
} Try / catch
if err := op(ctx); err != nil {
if strings.Contains(err.Error(), "checkout active branch") {
// recreate the branch or reopen the store pinned to an existing branch
}
return err
} Prevention
- Don't delete or rename the Dolt branch while a bd process is running.
- Keep the store's configured branch in sync with the repo's actual branches.
- Reopen the store after external branch surgery to reset pooled connections.
- Run bd doctor to verify branch/database state after rebuilds or migrations.
When it happens
Trigger: Executing any statement on a pooled connection when DOLT_CHECKOUT of the active branch fails — the branch was deleted/renamed on the connection's view, the database was rebuilt without that branch, or the SQL session errored.
Common situations: Branch deleted or renamed by another process between operations; repo directory re-initialized losing the recorded branch; mismatch between the store's configured branch and the database's actual branches; corrupted connection after a server restart.
Related errors
- iter dependents: acquire conn: %w
- failed to rebuild pool after migration: %w
- acquire connection for gc: %w
- acquire connection for remote-ref prune: %w
- acquire connection for flatten: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/8610021f30c101ee.
Report an issue: GitHub.