gofr-dev/gofr · error

requestsPerSecond must be positive

Error message

requestsPerSecond must be positive

What it means

errInvalidRequestsPerSecond is returned by RateLimiterConfig.Validate when RequestsPerSecond is zero or negative. The token-bucket rate limiter cannot function without a positive refill rate, so configuration is rejected up front.

Source

Thrown at pkg/gofr/http/middleware/rate_limiter.go:17

package middleware

import (
	"context"
	"errors"
	"fmt"
	"math"
	"net"
	"net/http"
	"strings"

	gofrHttp "gofr.dev/pkg/gofr/http"
)

var (
	// errInvalidRequestsPerSecond is returned when RequestsPerSecond is not positive.
	errInvalidRequestsPerSecond = errors.New("requestsPerSecond must be positive")

	// errInvalidBurst is returned when Burst is not positive.
	errInvalidBurst = errors.New("burst must be positive")
)

// RateLimiterConfig holds configuration for rate limiting.
//
// Note: The default implementation uses in-memory token buckets and is suitable
// for single-pod deployments. In multi-pod deployments, each pod will enforce
// limits independently. For distributed rate limiting across multiple pods,
// a Redis-backed store can be implemented in a future update.
//
// Security: When using PerIP=true, only enable TrustedProxies if your application
// is behind a trusted reverse proxy (nginx, ALB, etc.) that sets X-Forwarded-For.
// Without trusted proxies, clients can spoof IP addresses to bypass rate limits.
//
// Cleanup: The rate limiter starts a background goroutine that runs for the
// application lifetime. This is acceptable for long-running servers but consider

View on GitHub (pinned to 187eb24962)

Solutions

  1. Set RequestsPerSecond to a positive float (e.g. 10) in the RateLimiterConfig
  2. If loading from config/env, validate the parsed value is > 0 before building the middleware
  3. Provide a sensible default (e.g. 100) when the config value is missing

Example fix

// before
cfg := middleware.RateLimiterConfig{}
// after
cfg := middleware.RateLimiterConfig{RequestsPerSecond: 100, Burst: 200}
Defensive patterns

Strategy: validation

Validate before calling

if cfg.RequestsPerSecond <= 0 { return fmt.Errorf("RequestsPerSecond must be > 0, got %v", cfg.RequestsPerSecond) }

Type guard

func validRateConfig(c RateLimiterConfig) bool { return c.RequestsPerSecond > 0 && c.Burst > 0 }

Prevention

When it happens

Trigger: Constructing a RateLimiterConfig with RequestsPerSecond: 0, a negative value, or leaving it as the zero value in a struct literal that doesn't set it.

Common situations: Forgetting to set RequestsPerSecond because Go zero-values it; computing the rate from a config/env value that parses to 0; unit changes (per-minute vs per-second) yielding sub-1 values.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/bc71beb012a2e49f. Report an issue: GitHub.