gastownhall/beads · error
failed to check rows affected for issue counter prefix %q: %
Error message
failed to check rows affected for issue counter prefix %q: %w
What it means
After the counter UPDATE succeeds, NextCounterIDTx calls res.RowsAffected() to detect whether the prefix row existed. This error wraps a failure of RowsAffected() itself — the driver could not report the affected-row count for the executed UPDATE. It is a driver capability or connection issue, not a data problem.
Source
Thrown at internal/storage/issueops/helpers.go:238
func IsCounterModeTx(ctx context.Context, tx DBTX) (bool, error) {
var idMode string
err := tx.QueryRowContext(ctx, "SELECT value FROM config WHERE `key` = ?", "issue_id_mode").Scan(&idMode)
if err != nil && err != sql.ErrNoRows {
return false, fmt.Errorf("failed to read issue_id_mode config: %w", err)
}
return idMode == "counter", nil
}
// NextCounterIDTx atomically increments and returns the next sequential issue ID.
func NextCounterIDTx(ctx context.Context, tx DBTX, prefix string) (string, error) {
res, err := tx.ExecContext(ctx, "UPDATE issue_counter SET last_id = last_id + 1 WHERE prefix = ?", prefix)
if err != nil {
return "", fmt.Errorf("failed to increment issue counter for prefix %q: %w", prefix, err)
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return "", fmt.Errorf("failed to check rows affected for issue counter prefix %q: %w", prefix, err)
}
if rowsAffected == 0 {
if seedErr := SeedCounterFromExistingIssuesTx(ctx, tx, prefix); seedErr != nil {
return "", fmt.Errorf("failed to seed issue counter for prefix %q: %w", prefix, seedErr)
}
res, err = tx.ExecContext(ctx, "UPDATE issue_counter SET last_id = last_id + 1 WHERE prefix = ?", prefix)
if err != nil {
return "", fmt.Errorf("failed to increment issue counter after seeding for prefix %q: %w", prefix, err)
}
rowsAffected, err = res.RowsAffected()
if err != nil {
return "", fmt.Errorf("failed to check rows affected after seeding for prefix %q: %w", prefix, err)
}
if rowsAffected == 0 {
_, err = tx.ExecContext(ctx, "INSERT INTO issue_counter (prefix, last_id) VALUES (?, 1)", prefix)
if err != nil {
return "", fmt.Errorf("failed to insert initial issue counter for prefix %q: %w", prefix, err)View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped driver error; reconnect or reopen the database if it indicates a broken connection.
- If a stub or mock DBTX is in play, configure it to return a valid RowsAffected value (e.g. sqlmock WithRowsAffected(1)).
- Use the real Dolt driver rather than a shim that lacks RowsAffected support.
- Retry the operation if the cause is transient connection loss.
Example fix
// before: mock.ExpectExec("UPDATE issue_counter").WillReturnResult(sqlmock.NewErrorResult(errors.New("no rows"))) // after: mock.ExpectExec("UPDATE issue_counter").WillReturnResult(sqlmock.NewResult(0, 1)) Defensive patterns
Strategy: type-guard
Type guard
func isRowsAffectedErr(err error) bool { return err != nil && strings.Contains(err.Error(), "failed to check rows affected for issue counter prefix") } Try / catch
id, err := GenerateIssueIDInTable(ctx, tx, prefix, issue); if isRowsAffectedErr(err) { return fmt.Errorf("driver does not report rows affected: %w", err) } // surface immediately; do not blind-retry mocks Prevention
- Use the real Dolt driver; avoid custom DBTX shims lacking RowsAffected.
- In tests, always set sqlmock expectations with WithRowsAffected.
- Upgrade driver dependencies together with the app to keep Result semantics compatible.
- Check connection health around long operations so connections don't die mid-statement.
When it happens
Trigger: Calling NextCounterIDTx with a DBTX implementation whose Result does not support RowsAffected (custom or mock driver), a driver-level failure reading result metadata, or the underlying connection dying between ExecContext and RowsAffected.
Common situations: Tests or tooling injecting a stub DBTX (sqlmock misconfigured without a rows-affected result); using a driver variant that does not implement RowsAffected; intermittent connection reset right after executing the UPDATE.
Related errors
- db: LabelSQLRepository.Insert %s/%s: rows affected: %w
- db: RawSQL Exec: rows affected: %w
- failed to get rows affected: %w
- failed to check rows affected after seeding for prefix %q: %
- failed to check rows affected for issue counter prefix %q: %
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c6079417a49ba4c7.
Report an issue: GitHub.