{"id":"50465d38042512e3","repo":"labstack/echo","slug":"echo-rate-limiter-store-configuration-must-be-prov","errorCode":null,"errorMessage":"echo rate limiter store configuration must be provided","messagePattern":"echo rate limiter store configuration must be provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/rate_limiter.go","lineNumber":138,"sourceCode":"\treturn toMiddlewareOrPanic(config)\n}\n\n// ToMiddleware converts RateLimiterConfig to middleware or returns an error for invalid configuration\nfunc (config RateLimiterConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n\tif config.Skipper == nil {\n\t\tconfig.Skipper = DefaultRateLimiterConfig.Skipper\n\t}\n\tif config.IdentifierExtractor == nil {\n\t\tconfig.IdentifierExtractor = DefaultRateLimiterConfig.IdentifierExtractor\n\t}\n\tif config.ErrorHandler == nil {\n\t\tconfig.ErrorHandler = DefaultRateLimiterConfig.ErrorHandler\n\t}\n\tif config.DenyHandler == nil {\n\t\tconfig.DenyHandler = DefaultRateLimiterConfig.DenyHandler\n\t}\n\tif config.Store == nil {\n\t\treturn nil, errors.New(\"echo rate limiter store configuration must be provided\")\n\t}\n\treturn func(next echo.HandlerFunc) echo.HandlerFunc {\n\t\treturn func(c *echo.Context) error {\n\t\t\tif config.Skipper(c) {\n\t\t\t\treturn next(c)\n\t\t\t}\n\t\t\tif config.BeforeFunc != nil {\n\t\t\t\tconfig.BeforeFunc(c)\n\t\t\t}\n\n\t\t\tidentifier, err := config.IdentifierExtractor(c)\n\t\t\tif err != nil {\n\t\t\t\treturn config.ErrorHandler(c, err)\n\t\t\t}\n\n\t\t\tvar allow bool\n\t\t\tvar allowErr error\n\t\t\tif sc, ok := config.Store.(RateLimiterStoreContext); ok {","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/rate_limiter.go#L120-L156","documentation":"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.","triggerScenarios":"Calling RateLimiterWithConfig(RateLimiterConfig{...}) without setting Store, or assigning a nil store when a custom store constructor returned an error you ignored.","commonSituations":"Developer configures IdentifierExtractor/DenyHandler but forgets Store; or intends to plug in a Redis store later and leaves it nil in the meantime.","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."],"exampleFix":"// before\nm := middleware.RateLimiterWithConfig(middleware.RateLimiterConfig{\n    IdentifierExtractor: func(c *echo.Context) (string, error) { return c.RealIP(), nil },\n})\n// after\nm := middleware.RateLimiterWithConfig(middleware.RateLimiterConfig{\n    Store: middleware.NewRateLimiterMemoryStoreWithConfig(middleware.RateLimiterMemoryStoreConfig{Rate: 20, Burst: 40, ExpiresIn: 5 * time.Minute}),\n    IdentifierExtractor: func(c *echo.Context) (string, error) { return c.RealIP(), nil },\n})","handlingStrategy":"validation","validationCode":"func rateLimiterMiddleware(rate float64, burst int) (echo.MiddlewareFunc, error) {\n    cfg := middleware.RateLimiterConfig{Store: middleware.NewRateLimiterMemoryStoreWithConfig(middleware.RateLimiterMemoryStoreConfig{Rate: rate, Burst: burst})}\n    if cfg.Store == nil {\n        return nil, errors.New(\"rate limiter requires a Store\")\n    }\n    return cfg.ToMiddleware()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["middleware","rate-limiter","config","panic","startup"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}