cloudflare/cloudflared · error
failed to bind to address (%s): %w
Error message
failed to bind to address (%s): %w
What it means
Returned when cloudflared is given an explicit metrics listen address and listeners.Listen("tcp", laddr) fails to bind it. The configured address is included in the message and the underlying net.OpError is wrapped. This is the explicit-address counterpart of the default-address bind failure.
Source
Thrown at metrics/metrics.go:137
listener, err := listeners.Listen("tcp", address)
if err == nil {
return listener, nil
}
}
// When no port is available then bind to a random one
listener, err := listeners.Listen("tcp", laddr)
if err != nil {
return nil, fmt.Errorf("failed to listen to default metrics address: %w", err)
}
return listener, nil
}
// Explicitly got a local address then bind to it
listener, err := listeners.Listen("tcp", laddr)
if err != nil {
return nil, fmt.Errorf("failed to bind to address (%s): %w", laddr, err)
}
return listener, nil
}
func ServeMetrics(
l net.Listener,
ctx context.Context,
config Config,
log *zerolog.Logger,
) (err error) {
var wg sync.WaitGroup
// Metrics port is privileged, so no need for further access control
trace.AuthRequest = func(*http.Request) (bool, bool) { return true, true }
h := newMetricsHandler(config, log)
server := &http.Server{
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,View on GitHub (pinned to 2253eeeb25)
Solutions
- Inspect the wrapped cause: 'address already in use' → free the port; 'cannot assign requested address' → fix the IP/host
- Choose a free port and update --metrics (e.g. --metrics 127.0.0.1:33755)
- Bind to 0.0.0.0 or localhost instead of a stale interface IP
- Verify /etc/hosts or DNS resolves the hostname in the metrics address
Example fix
// before cloudflared tunnel run --metrics 127.0.0.1:20241 # already in use // after cloudflared tunnel run --metrics 127.0.0.1:20242 # verified free with ss -ltnp
Defensive patterns
Strategy: validation
Validate before calling
func metricsAddrBindable(addr string) error {
ln, err := net.Listen("tcp", addr)
if err != nil {
return fmt.Errorf("metrics address %s not bindable: %w", addr, err)
}
return ln.Close()
}
// run before launching cloudflared with --metrics <addr> Prevention
- Verify the address is bindable with ss -ltnp / a pre-flight net.Listen before deploy
- Avoid ports <1024 for metrics without root or CAP_NET_BIND_SERVICE
- Use 127.0.0.1 with distinct ports per instance; avoid interface IPs that can disappear on DHCP change
When it happens
Trigger: Calling ServeMetrics / StartMetricsServer with an explicit --metrics address that is already bound by another process, is malformed, resolves to an address not present on the host, or requires privileges (ports <1024).
Common situations: --metrics pointing at a port another daemon already uses; binding to a specific interface IP that no longer exists (DHCP change); typo in host causing resolver failure; running in a container without the IP; two services configured with the same metrics port in deployment manifests.
Related errors
- failed to listen to default metrics address: %w
- failed to start forwarding server
- Error opening metrics server listener
- failed to build quick tunnel request
- failed to request quick Tunnel
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/70539ab9383830ec.
Report an issue: GitHub.