{"record":{"id":"ad5bb5b128be3753","repo":"gastownhall/beads","slug":"db-claim-s-rows-affected-w","errorCode":null,"errorMessage":"db: Claim %s: rows affected: %w","messagePattern":"db: Claim (.+?): rows affected: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/issue.go","lineNumber":489,"sourceCode":"\t\t\t\tWHERE id = ? AND row_lock = ? AND (%s)\n\t\t\t`, table, rowLockClause, statusPredicate), args...)\n\t\t} else {\n\t\t\targs := append([]any{actor, now}, rowLockArgs...)\n\t\t\targs = append(args, id, oldIssue.RowVersion)\n\t\t\targs = append(args, statusArgs...)\n\t\t\t//nolint:gosec // G201: table is one of two hardcoded constants\n\t\t\tres, err = r.runner.ExecContext(ctx, fmt.Sprintf(`\n\t\t\t\tUPDATE %s\n\t\t\t\tSET assignee = ?, status = 'in_progress', updated_at = ?, %s\n\t\t\t\tWHERE id = ? AND row_lock = ? AND (%s)\n\t\t\t`, table, rowLockClause, statusPredicate), args...)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn domain.ClaimRowResult{}, fmt.Errorf(\"db: Claim %s: %w\", id, err)\n\t\t}\n\t\trows, err = res.RowsAffected()\n\t\tif err != nil {\n\t\t\treturn domain.ClaimRowResult{}, fmt.Errorf(\"db: Claim %s: rows affected: %w\", id, err)\n\t\t}\n\t}\n\n\tif rows == 0 {\n\t\tvar currentAssignee sql.NullString\n\t\tvar currentStatus types.Status\n\t\t//nolint:gosec // G201: table is one of two hardcoded constants\n\t\tif err := r.runner.QueryRowContext(ctx,\n\t\t\tfmt.Sprintf(\"SELECT assignee, status FROM %s WHERE id = ?\", table), id,\n\t\t).Scan(&currentAssignee, &currentStatus); err != nil {\n\t\t\treturn domain.ClaimRowResult{}, fmt.Errorf(\"db: Claim %s: read current state: %w\", id, err)\n\t\t}\n\t\tassignee := \"\"\n\t\tif currentAssignee.Valid {\n\t\t\tassignee = currentAssignee.String\n\t\t}\n\t\treturn domain.ClaimRowResult{\n\t\t\tUpdated:               false,","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/issue.go#L471-L507","documentation":"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.","triggerScenarios":"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.","commonSituations":"Unstable network to a remote Dolt server; driver quirks where RowsAffected errors despite successful execution; pooled connections invalidated server-side.","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."],"exampleFix":"// before\nres, err := store.Claim(ctx, id, actor, opts) // opaque RowsAffected failure\n// after\nif err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) { res, err = store.Claim(ctx, id, actor, opts) }\n}","handlingStrategy":"retry","validationCode":"if err := pingStore(ctx); err != nil { return fmt.Errorf(\"store unreachable: %w\", err) }","typeGuard":null,"tryCatchPattern":"res, err := store.Claim(ctx, id, actor, opts)\nif err != nil && errors.Is(err, driver.ErrBadConn) {\n    res, err = store.Claim(ctx, id, actor, opts) // rolled-back tx, safe retry\n}","preventionTips":["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."],"tags":["database","driver","rows-affected"],"backgroundTag":"driver-rows-affected-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}