{"id":"1d6bc6de3673e96c","repo":"labstack/echo","slug":"echo-proxy-middleware-requires-balancer","errorCode":null,"errorMessage":"echo proxy middleware requires balancer","messagePattern":"echo proxy middleware requires balancer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/proxy.go","lineNumber":314,"sourceCode":"}\n\n// ProxyWithConfig returns a Proxy middleware or panics if configuration is invalid.\n//\n// Proxy middleware forwards the request to upstream server using a configured load balancing technique.\nfunc ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {\n\treturn toMiddlewareOrPanic(config)\n}\n\n// ToMiddleware converts ProxyConfig to middleware or returns an error for invalid configuration\nfunc (config ProxyConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n\tif config.Skipper == nil {\n\t\tconfig.Skipper = DefaultProxyConfig.Skipper\n\t}\n\tif config.ContextKey == \"\" {\n\t\tconfig.ContextKey = DefaultProxyConfig.ContextKey\n\t}\n\tif config.Balancer == nil {\n\t\treturn nil, errors.New(\"echo proxy middleware requires balancer\")\n\t}\n\tif config.RetryFilter == nil {\n\t\tconfig.RetryFilter = func(c *echo.Context, e error) bool {\n\t\t\tif httpErr, ok := e.(*echo.HTTPError); ok {\n\t\t\t\treturn httpErr.Code == http.StatusBadGateway\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}\n\tif config.ErrorHandler == nil {\n\t\tconfig.ErrorHandler = func(c *echo.Context, err error) error {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif config.Rewrite != nil {\n\t\tif config.RegexRewrite == nil {\n\t\t\tconfig.RegexRewrite = make(map[*regexp.Regexp]string)","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/proxy.go#L296-L332","documentation":"Returned by ProxyConfig.ToMiddleware when config.Balancer is nil. The proxy middleware forwards each request to a target chosen by the balancer; without one there is no target-selection strategy. Build a balancer with NewRoundRobinBalancer or NewRandomBalancer from a list of *ProxyTarget.","triggerScenarios":"Calling ProxyWithConfig(ProxyConfig{...}) without setting Balancer, or assigning a nil balancer variable (e.g., when the targets list is empty and you skip constructing one).","commonSituations":"Developer constructs the balancer conditionally based on env config and the branch leaves it nil; or migrates from Proxy(balancer) to ProxyWithConfig and forgets to carry Balancer over.","solutions":["Construct a balancer: middleware.NewRoundRobinBalancer([]*middleware.ProxyTarget{{URL: mustParseURL(\"http://upstream:8080\")}}) and set it as config.Balancer.","Prefer the shorthand Proxy(balancer) when you only need a balancer.","Fail fast at startup if the targets list is empty rather than passing a nil balancer.","Use config.ToMiddleware() to get the error returned instead of panicked."],"exampleFix":"// before\nm := middleware.ProxyWithConfig(middleware.ProxyConfig{\n    Rewrite: map[string]string{\"/old/*\": \"/$1\"},\n})\n// after\ntargets := []*middleware.ProxyTarget{{Name: \"upstream\", URL: mustParseURL(\"http://upstream:8080\")}}\nm := middleware.ProxyWithConfig(middleware.ProxyConfig{\n    Balancer: middleware.NewRoundRobinBalancer(targets),\n    Rewrite:  map[string]string{\"/old/*\": \"/$1\"},\n})","handlingStrategy":"validation","validationCode":"func proxyMiddleware(targets []*middleware.ProxyTarget) (echo.MiddlewareFunc, error) {\n    if len(targets) == 0 {\n        return nil, errors.New(\"proxy requires at least one target\")\n    }\n    cfg := middleware.ProxyConfig{Balancer: middleware.NewRoundRobinBalancer(targets)}\n    return cfg.ToMiddleware()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always construct a balancer via NewRoundRobinBalancer / NewRandomBalancer and assign it to config.Balancer.","Prefer Proxy(balancer) when you do not need other ProxyConfig fields.","Use cfg.ToMiddleware() to surface a missing balancer as an error."],"tags":["middleware","proxy","config","panic","startup"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}