gastownhall/beads · error
db: Claim %s: rows affected: %w
Error message
db: Claim %s: rows affected: %w
What it means
This error wraps a failure of res.RowsAffected() after the claim UPDATE executed. If the driver cannot report the affected-row count, Claim cannot tell whether the CAS succeeded and aborts with this wrapped error.
Source
Thrown at internal/storage/domain/db/issue.go:489
WHERE id = ? AND row_lock = ? AND (%s)
`, table, rowLockClause, statusPredicate), args...)
} else {
args := append([]any{actor, now}, rowLockArgs...)
args = append(args, id, oldIssue.RowVersion)
args = append(args, statusArgs...)
//nolint:gosec // G201: table is one of two hardcoded constants
res, err = r.runner.ExecContext(ctx, fmt.Sprintf(`
UPDATE %s
SET assignee = ?, status = 'in_progress', updated_at = ?, %s
WHERE id = ? AND row_lock = ? AND (%s)
`, table, rowLockClause, statusPredicate), args...)
}
if err != nil {
return domain.ClaimRowResult{}, fmt.Errorf("db: Claim %s: %w", id, err)
}
rows, err = res.RowsAffected()
if err != nil {
return domain.ClaimRowResult{}, fmt.Errorf("db: Claim %s: rows affected: %w", id, err)
}
}
if rows == 0 {
var currentAssignee sql.NullString
var currentStatus types.Status
//nolint:gosec // G201: table is one of two hardcoded constants
if err := r.runner.QueryRowContext(ctx,
fmt.Sprintf("SELECT assignee, status FROM %s WHERE id = ?", table), id,
).Scan(¤tAssignee, ¤tStatus); err != nil {
return domain.ClaimRowResult{}, fmt.Errorf("db: Claim %s: read current state: %w", id, err)
}
assignee := ""
if currentAssignee.Valid {
assignee = currentAssignee.String
}
return domain.ClaimRowResult{
Updated: false,View on GitHub (pinned to 71377f2769)
Solutions
- Retry the claim — the transaction rolled back so the CAS can be re-run cleanly.
- Check network/driver stability between client and database server.
- Verify the driver version supports RowsAffected for UPDATE statements.
- Inspect the wrapped cause for connection-reset signatures and reconnect.
Example fix
// before
res, err := store.Claim(ctx, id, actor, opts) // opaque RowsAffected failure
// after
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) { res, err = store.Claim(ctx, id, actor, opts) }
} Defensive patterns
Strategy: retry
Validate before calling
if err := pingStore(ctx); err != nil { return fmt.Errorf("store unreachable: %w", err) } Try / catch
res, err := store.Claim(ctx, id, actor, opts)
if err != nil && errors.Is(err, driver.ErrBadConn) {
res, err = store.Claim(ctx, id, actor, opts) // rolled-back tx, safe retry
} Prevention
- Keep connections alive with health checks/pings for remote databases.
- Use a current driver version with reliable RowsAffected support.
- Avoid claim operations over flaky network links; run near the DB.
- Set connection pool max lifetimes below server idle cutoffs.
When it happens
Trigger: Calling Claim with a driver/connection where RowsAffected errors after the UPDATE: broken connection returned with the result, driver limitation, or mid-statement connection teardown.
Common situations: Unstable network to a remote Dolt server; driver quirks where RowsAffected errors despite successful execution; pooled connections invalidated server-side.
Related errors
- failed to check rows affected for issue counter prefix %q: %
- failed to check rows affected after seeding for prefix %q: %
- db: DependencySQLRepository.DeleteAllForIDs rows affected: %
- db: EventsSQLRepository.DeleteAllForIDs rows affected: %w
- db: Update %s: rows affected: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ad5bb5b128be3753.
Report an issue: GitHub.