gastownhall/beads · warning

db: RawSQL Exec: rows affected: %w

Error message

db: RawSQL Exec: rows affected: %w

What it means

Wraps a failure from sql.Result.RowsAffected after a successful Exec in RawSQLRepository.Exec. Some drivers cannot report affected-row counts for certain statements, and the driver can also fail here if the connection state is gone. The statement executed but the library cannot tell you how many rows it touched.

Source

Thrown at internal/storage/domain/db/raw_sql.go:62

				values[i] = string(b)
			}
		}
		result.Rows = append(result.Rows, values)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("db: RawSQL Query: rows: %w", err)
	}
	return result, nil
}

func (r *rawSQLRepositoryImpl) Exec(ctx context.Context, query string, args ...any) (int64, error) {
	res, err := r.runner.ExecContext(ctx, query, args...)
	if err != nil {
		return 0, fmt.Errorf("db: RawSQL Exec: %w", err)
	}
	affected, err := res.RowsAffected()
	if err != nil {
		return 0, fmt.Errorf("db: RawSQL Exec: rows affected: %w", err)
	}
	return affected, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Treat the count as optional — if you don't need it, prefer a driver/connection that supports RowsAffected or ignore 0
  2. Avoid Exec for DDL when you rely on affected counts
  3. Check driver support; upgrade if RowsAffected is unimplemented
  4. Verify connection stability — a drop right after exec yields an unusable result handle

Example fix

// before: relying on the count for a DDL statement
n, err := repo.Exec(ctx, "ALTER TABLE issues ADD INDEX idx_p (priority)")
// after: don't depend on the affected count for DDL
_, err = repo.Exec(ctx, "ALTER TABLE issues ADD INDEX idx_p (priority)")
Defensive patterns

Strategy: fallback

Validate before calling

// don't rely on affected counts for DDL; classify the statement first
isDDL := strings.HasPrefix(strings.ToUpper(strings.TrimSpace(stmt)), "ALTER") ||
	strings.HasPrefix(strings.ToUpper(strings.TrimSpace(stmt)), "CREATE")

Type guard

func isRowsAffectedError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "RawSQL Exec: rows affected")
}

Try / catch

n, err := repo.Exec(ctx, stmt)
if isRowsAffectedError(err) {
	// statement ran; proceed treating the count as unknown
	return lastErr /* or continue without the count */
}

Prevention

When it happens

Trigger: Calling Exec with a statement whose driver (or underlying engine) does not produce a rows-affected count, or where the result handle is invalid because the connection dropped after execution.

Common situations: Statements like DDL (CREATE/ALTER) or some multi-statement/SET commands where affected counts are meaningless; drivers lacking LastInsertId/RowsAffected support; connection reset immediately after exec.

Related errors


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