gofr-dev/gofr · critical

invalid rate limiter config: %v

Error message

invalid rate limiter config: %v

What it means

This is a panic message raised inside the RateLimiter middleware constructor when config.Validate() returns an error (non-positive RequestsPerSecond or Burst). Invalid rate limiting configuration is treated as a programming/deployment error, so it fails fast at startup rather than at request time.

Source

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

	realIP := r.Header.Get("X-Real-IP")
	return strings.TrimSpace(realIP)
}

// getRemoteAddr extracts IP from RemoteAddr.
func getRemoteAddr(r *http.Request) string {
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return r.RemoteAddr
	}

	return ip
}

// RateLimiter creates a middleware that limits requests based on the configuration.
func RateLimiter(config RateLimiterConfig, m metrics) func(http.Handler) http.Handler {
	// Validate configuration
	if err := config.Validate(); err != nil {
		panic(fmt.Sprintf("invalid rate limiter config: %v", err))
	}

	// Use in-memory store if none provided
	if config.Store == nil {
		config.Store = NewMemoryRateLimiterStore(config)
	}

	// Start cleanup routine with context.Background().
	// The cleanup goroutine runs for the application lifetime.
	// For graceful shutdown, call config.Store.StopCleanup() in your shutdown handler.
	ctx := context.Background()
	config.Store.StartCleanup(ctx)

	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// Skip rate limiting for health check endpoints
			if isWellKnown(r.URL.Path) {
				next.ServeHTTP(w, r)

View on GitHub (pinned to 187eb24962)

Solutions

  1. Fix the RateLimiterConfig values so RequestsPerSecond > 0 and Burst > 0 before calling RateLimiter()
  2. Call config.Validate() yourself earlier and log/exit with a friendly message instead of reaching the panic
  3. Sanitize env/config parsing: treat missing or zero rate values as defaults at load time

Example fix

// before
middleware.RateLimiter(middleware.RateLimiterConfig{RequestsPerSecond: rps}) // rps=0 from env
// after
if rps <= 0 { rps = 100 }
if burst <= 0 { burst = 200 }
middleware.RateLimiter(middleware.RateLimiterConfig{RequestsPerSecond: rps, Burst: burst})
Defensive patterns

Strategy: validation

Validate before calling

if err := cfg.Validate(); err != nil { logger.Fatalf("rate limiter misconfigured: %v", err) }

Type guard

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

Try / catch

defer func() { if r := recover(); r != nil { logger.Fatalf("rate limiter init panicked: %v", r) } }() // around middleware wiring

Prevention

When it happens

Trigger: Calling middleware.RateLimiter(RateLimiterConfig{...}) with RequestsPerSecond <= 0 or Burst <= 0; typically during server bootstrap.

Common situations: Deployment misconfiguration where rate limit env vars are empty and parse to 0; refactoring that drops a field from the config literal; test setups that forget to populate the config.

Related errors


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