gastownhall/beads · error

failed to check rows affected after seeding for prefix %q: %

Error message

failed to check rows affected after seeding for prefix %q: %w

What it means

After the post-seed increment, NextCounterIDTx calls res.RowsAffected() a second time to confirm the counter row was actually updated. This error wraps a failure of that RowsAffected call — the driver could not report the affected row count for the post-seed UPDATE. It indicates a driver or connection problem rather than missing data.

Source

Thrown at internal/storage/issueops/helpers.go:251

		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)
			}
		}
	}

	var nextID int
	err = tx.QueryRowContext(ctx, "SELECT last_id FROM issue_counter WHERE prefix = ?", prefix).Scan(&nextID)
	if err != nil {
		return "", fmt.Errorf("failed to read issue counter after increment for prefix %q: %w", prefix, err)
	}
	return fmt.Sprintf("%s-%d", prefix, nextID), nil
}

// SeedCounterFromExistingIssuesTx scans existing issues to find the highest numeric suffix

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error; reconnect and retry if it signals connection loss.
  2. Fix the mock or stub to return a proper Result (sqlmock.NewResult(0, 1)) for the post-seed UPDATE expectation.
  3. Pin or upgrade to a driver version whose RowsAffected works for UPDATE results.
  4. Retry issue creation if the cause is a transient network drop.

Example fix

// before: mock.ExpectExec("UPDATE issue_counter").WillReturnResult(invalidResult) // after: mock.ExpectExec("UPDATE issue_counter").WillReturnResult(sqlmock.NewResult(0, 1))
Defensive patterns

Strategy: try-catch

Type guard

func isPostSeedRowsAffectedErr(err error) bool { return err != nil && strings.Contains(err.Error(), "failed to check rows affected after seeding for prefix") }

Try / catch

id, err := GenerateIssueIDInTable(ctx, tx, prefix, issue); if isPostSeedRowsAffectedErr(err) { return fmt.Errorf("rows-affected unavailable: %w", err) } // fix driver or mock, then retry once

Prevention

When it happens

Trigger: Calling NextCounterIDTx on a prefix that required seeding, where the driver fails to report rows affected for the second UPDATE: broken connection between ExecContext and RowsAffected, a DBTX stub (mock) that errors on result introspection, or a driver lacking RowsAffected support for this statement.

Common situations: Test suites using misconfigured sqlmock or stub DBTX for the second statement; flaky network to a remote Dolt server dropping results mid-response; driver incompatibilities after a dependency upgrade.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/e427454e5a3bb2a9. Report an issue: GitHub.