labstack/echo · error
echo proxy middleware requires balancer
Error message
echo proxy middleware requires balancer
What it means
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.
Source
Thrown at middleware/proxy.go:314
}
// ProxyWithConfig returns a Proxy middleware or panics if configuration is invalid.
//
// Proxy middleware forwards the request to upstream server using a configured load balancing technique.
func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
return toMiddlewareOrPanic(config)
}
// ToMiddleware converts ProxyConfig to middleware or returns an error for invalid configuration
func (config ProxyConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
if config.Skipper == nil {
config.Skipper = DefaultProxyConfig.Skipper
}
if config.ContextKey == "" {
config.ContextKey = DefaultProxyConfig.ContextKey
}
if config.Balancer == nil {
return nil, errors.New("echo proxy middleware requires balancer")
}
if config.RetryFilter == nil {
config.RetryFilter = func(c *echo.Context, e error) bool {
if httpErr, ok := e.(*echo.HTTPError); ok {
return httpErr.Code == http.StatusBadGateway
}
return false
}
}
if config.ErrorHandler == nil {
config.ErrorHandler = func(c *echo.Context, err error) error {
return err
}
}
if config.Rewrite != nil {
if config.RegexRewrite == nil {
config.RegexRewrite = make(map[*regexp.Regexp]string)View on GitHub (pinned to 05489dc173)
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.
Example fix
// before
m := middleware.ProxyWithConfig(middleware.ProxyConfig{
Rewrite: map[string]string{"/old/*": "/$1"},
})
// after
targets := []*middleware.ProxyTarget{{Name: "upstream", URL: mustParseURL("http://upstream:8080")}}
m := middleware.ProxyWithConfig(middleware.ProxyConfig{
Balancer: middleware.NewRoundRobinBalancer(targets),
Rewrite: map[string]string{"/old/*": "/$1"},
}) Defensive patterns
Strategy: validation
Validate before calling
func proxyMiddleware(targets []*middleware.ProxyTarget) (echo.MiddlewareFunc, error) {
if len(targets) == 0 {
return nil, errors.New("proxy requires at least one target")
}
cfg := middleware.ProxyConfig{Balancer: middleware.NewRoundRobinBalancer(targets)}
return cfg.ToMiddleware()
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
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 rate limiter store configuration must be provided
AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04).
Data as JSON: /data/errors/1d6bc6de3673e96c.json.
Report an issue: GitHub.