labstack/echo · error

echo rate limiter store configuration must be provided

Error message

echo rate limiter store configuration must be provided

What it means

Returned by RateLimiterConfig.ToMiddleware when config.Store is nil. The store holds per-identifier rate state and answers Allow(id); without it the limiter has no memory and cannot enforce a rate. The built-in in-memory store is created with NewRateLimiterMemoryStore or NewRateLimiterMemoryStoreWithConfig.

Source

Thrown at middleware/rate_limiter.go:138

	return toMiddlewareOrPanic(config)
}

// ToMiddleware converts RateLimiterConfig to middleware or returns an error for invalid configuration
func (config RateLimiterConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
	if config.Skipper == nil {
		config.Skipper = DefaultRateLimiterConfig.Skipper
	}
	if config.IdentifierExtractor == nil {
		config.IdentifierExtractor = DefaultRateLimiterConfig.IdentifierExtractor
	}
	if config.ErrorHandler == nil {
		config.ErrorHandler = DefaultRateLimiterConfig.ErrorHandler
	}
	if config.DenyHandler == nil {
		config.DenyHandler = DefaultRateLimiterConfig.DenyHandler
	}
	if config.Store == nil {
		return nil, errors.New("echo rate limiter store configuration must be provided")
	}
	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c *echo.Context) error {
			if config.Skipper(c) {
				return next(c)
			}
			if config.BeforeFunc != nil {
				config.BeforeFunc(c)
			}

			identifier, err := config.IdentifierExtractor(c)
			if err != nil {
				return config.ErrorHandler(c, err)
			}

			var allow bool
			var allowErr error
			if sc, ok := config.Store.(RateLimiterStoreContext); ok {

View on GitHub (pinned to 05489dc173)

Solutions

  1. Create the built-in store: middleware.NewRateLimiterMemoryStore(20) for 20 req/s, or NewRateLimiterMemoryStoreWithConfig for rate+burst+expiresIn.
  2. Prefer the shorthand RateLimiter(store) when you only need the default extractor/handlers.
  3. For distributed deployments, pass a store implementing RateLimiterStore (and optionally RateLimiterStoreContext for X-RateLimit headers).
  4. Use config.ToMiddleware() to receive the error rather than a panic.

Example fix

// before
m := middleware.RateLimiterWithConfig(middleware.RateLimiterConfig{
    IdentifierExtractor: func(c *echo.Context) (string, error) { return c.RealIP(), nil },
})
// after
m := middleware.RateLimiterWithConfig(middleware.RateLimiterConfig{
    Store: middleware.NewRateLimiterMemoryStoreWithConfig(middleware.RateLimiterMemoryStoreConfig{Rate: 20, Burst: 40, ExpiresIn: 5 * time.Minute}),
    IdentifierExtractor: func(c *echo.Context) (string, error) { return c.RealIP(), nil },
})
Defensive patterns

Strategy: validation

Validate before calling

func rateLimiterMiddleware(rate float64, burst int) (echo.MiddlewareFunc, error) {
    cfg := middleware.RateLimiterConfig{Store: middleware.NewRateLimiterMemoryStoreWithConfig(middleware.RateLimiterMemoryStoreConfig{Rate: rate, Burst: burst})}
    if cfg.Store == nil {
        return nil, errors.New("rate limiter requires a Store")
    }
    return cfg.ToMiddleware()
}

Prevention

When it happens

Trigger: Calling RateLimiterWithConfig(RateLimiterConfig{...}) without setting Store, or assigning a nil store when a custom store constructor returned an error you ignored.

Common situations: Developer configures IdentifierExtractor/DenyHandler but forgets Store; or intends to plug in a Redis store later and leaves it nil in the meantime.

Related errors


AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04). Data as JSON: /data/errors/50465d38042512e3.json. Report an issue: GitHub.