gastownhall/beads · error
failed to claim issue: %w
Error message
failed to claim issue: %w
What it means
ClaimIssueInTx wraps any error returned by the database driver when executing the claim compare-and-swap UPDATE (setting assignee/status='in_progress' guarded on row_lock and claimable status). This means the SQL execution itself failed — not that the claim was refused — so the claim did not happen and the wrapped driver error carries the root cause (connection loss, syntax/constraint error, context cancellation).
Source
Thrown at internal/storage/issueops/claim.go:130
args = append(args, id, oldIssue.RowVersion)
args = append(args, statusArgs...)
result, err = tx.ExecContext(ctx, fmt.Sprintf(`
UPDATE %s
SET assignee = ?, status = 'in_progress', updated_at = ?, started_at = ?, %s
WHERE id = ? AND row_lock = ? AND status IN (%s)
`, issueTable, rowLockClause, statusPlaceholders), args...)
} else {
args := append([]interface{}{actor, now}, rowLockArgs...)
args = append(args, id, oldIssue.RowVersion)
args = append(args, statusArgs...)
result, err = tx.ExecContext(ctx, fmt.Sprintf(`
UPDATE %s
SET assignee = ?, status = 'in_progress', updated_at = ?, %s
WHERE id = ? AND row_lock = ? AND status IN (%s)
`, issueTable, rowLockClause, statusPlaceholders), args...)
}
if err != nil {
return nil, fmt.Errorf("failed to claim issue: %w", err)
}
rowsAffected, err = result.RowsAffected()
if err != nil {
return nil, fmt.Errorf("failed to get rows affected: %w", err)
}
}
if rowsAffected == 0 {
assignee, currentStatus, err := readClaimStateInTx(ctx, tx, issueTable, id)
if err != nil {
return nil, fmt.Errorf("failed to get current claim state: %w", err)
}
// Idempotent: if already claimed in_progress by the same actor —
// including a spelling difference across layers (ga-wzl83) — treat as
// success. This supports agent retry workflows where claim may be
// called multiple times after transient failures (GH#8).
if actorMatches(assignee, actor) && currentStatus == types.StatusInProgress {
return &ClaimResult{OldIssue: oldIssue, IsWisp: isWisp}, nilView on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped driver error (%w) for the root cause and fix it (reconnect, restart server, etc.)
- Retry the claim — the CAS is idempotent for the same actor once in_progress
- Check DB connectivity/schema version (bd doctor) if the failure is persistent
Example fix
// before
issued, err := ClaimIssueInTx(ctx, tx, id, actor) // raw failure surfaces here
// after
issued, err := ClaimIssueInTx(ctx, tx, id, actor)
if err != nil {
var conflict *publicops.ClaimConflictError
if !errors.As(err, &conflict) { // only transient/infra failures fall through
time.Sleep(backoff); return ClaimIssueInTx(ctx, tx, id, actor)
}
return nil, err
} Defensive patterns
Strategy: retry
Validate before calling
// ensure connectivity before claiming
if err := db.PingContext(ctx); err != nil { return fmt.Errorf("db unavailable: %w", err) } Try / catch
res, err := ClaimIssueInTx(ctx, tx, id, actor)
if err != nil {
var conflict *publicops.ClaimConflictError
if errors.As(err, &conflict) { return handleConflict(conflict) }
if errors.Is(ctx.Err(), context.Canceled) { return ctx.Err() }
return retryWithBackoff(func() error { _, err := ClaimIssueInTx(ctx, tx, id, actor); return err })
} Prevention
- Keep the DB connection healthy (timeouts, pings) before claim bursts
- Distinguish claim conflicts (typed ClaimConflictError) from infra errors before retrying
- Use bounded retries with backoff — the CAS is idempotent for the same actor
When it happens
Trigger: Calling ClaimIssueInTx (via bd claim, ClaimReadyIssueInTx, ExecuteUpdate, ExecuteClaim) when the backing Dolt/SQL connection errors on the UPDATE: dropped connection, canceled context, constraint violation, or a backend engine error during the CAS write.
Common situations: Network blip between the CLI and the Dolt server mid-claim; the transaction's context deadline exceeded on a slow/loaded server; a driver/schema mismatch after upgrading bd while the DB is an older version.
Related errors
- set repo mtime: %w
- clear repo mtime: %w
- failed to get current claim state: %w
- failed to record claim event: %w
- get claimed issue: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/2229b5dc111e004c.
Report an issue: GitHub.