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
- Create the built-in store: middleware.NewRateLimiterMemoryStore(20) for 20 req/s, or NewRateLimiterMemoryStoreWithConfig for rate+burst+expiresIn.
- Prefer the shorthand RateLimiter(store) when you only need the default extractor/handlers.
- For distributed deployments, pass a store implementing RateLimiterStore (and optionally RateLimiterStoreContext for X-RateLimit headers).
- 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
- Always create a store (NewRateLimiterMemoryStore or a distributed implementation) and assign it to config.Store.
- Prefer RateLimiter(store) when you only need the defaults.
- For multi-instance deployments, use a shared store (Redis, etc.) implementing RateLimiterStore.
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
- timeout must be set
- at least one AllowOrigins is required or UnsafeAllowOriginFu
- echo key-auth middleware requires a validator function
- echo key-auth middleware could not create extractors from Ke
- echo proxy middleware requires balancer
AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04).
Data as JSON: /data/errors/50465d38042512e3.json.
Report an issue: GitHub.