cloudflare/cloudflared · error
Error opening metrics server listener
Error message
Error opening metrics server listener
What it means
cloudflared wraps the error returned by metrics.CreateMetricsListener when the metrics HTTP server cannot open its listener socket. The metrics listener binds an address like 127.0.0.1:metrics (or --metrics value) so prometheus metrics can be scraped; if that bind fails the tunnel refuses to start. The error is both logged and wrapped before aborting StartServer.
Source
Thrown at cmd/cloudflared/tunnel/cmd.go:462
mgmt := management.New(
managementHostname,
c.Bool("management-diagnostics"),
serviceIP,
connectorID,
c.String(cfdflags.ConnectorLabel),
logger.ManagementLogger.Log,
logger.ManagementLogger,
)
internalRules := []ingress.Rule{ingress.NewManagementRule(mgmt)}
orchestrator, err := orchestration.NewOrchestrator(ctx, orchestratorConfig, tunnelConfig.Tags, internalRules, tunnelConfig.Log)
if err != nil {
return err
}
metricsListener, err := metrics.CreateMetricsListener(&listeners, c.String("metrics"))
if err != nil {
log.Err(err).Msg("Error opening metrics server listener")
return errors.Wrap(err, "Error opening metrics server listener")
}
defer func() { _ = metricsListener.Close() }()
wg.Add(1)
go func() {
defer wg.Done()
tracker := tunnelstate.NewConnTracker(log)
observer.RegisterSink(tracker)
ipv4, ipv6, err := determineICMPSources(c, log)
sources := make([]string, 0)
if err == nil {
sources = append(sources, ipv4.String())
sources = append(sources, ipv6.String())
}
readinessServer := metrics.NewReadyServer(connectorID, tracker)View on GitHub (pinned to 2253eeeb25)
Solutions
- Check what is using the metrics port (lsof -i :<port> / netstat) and stop the conflicting process.
- Set --metrics to a free address/port, e.g. --metrics 127.0.0.1:20241, or 127.0.0.1:0 to pick an ephemeral port.
- Disable metrics entirely with --metrics none if scraping is not needed.
- Verify the --metrics value is a valid host:port; fix typos or out-of-range ports.
Example fix
// before cloudflared tunnel run --metrics localhost:20241 my-tunnel // error: port already in use // after cloudflared tunnel run --metrics 127.0.0.1:20245 my-tunnel
Defensive patterns
Strategy: validation
Validate before calling
// check the port is free before starting
import "net"
func metricsAddrAvailable(addr string) bool {
ln, err := net.Listen("tcp", addr)
if err != nil { return false }
_ = ln.Close()
return true
} Try / catch
if err != nil {
log.Err(err).Msg("Error opening metrics server listener")
return fmt.Errorf("metrics listener on %s unavailable: %w", metricsAddr, err)
} Prevention
- Pick a unique metrics port per cloudflared instance
- Use 127.0.0.1:0 for an ephemeral port when scraping config can follow the logs
- Use `--metrics none` when metrics are not needed
- Monitor ports with lsof/netstat before deployments
When it happens
Trigger: Running `cloudflared tunnel run` (via RunQuickTunnel or runWithCredentials -> StartServer) with a --metrics address that is already bound, invalid, or unbindable (e.g. privileged port without permissions, bad hostname).
Common situations: Two cloudflared instances running with the same default metrics port (2024x); container environments where 0.0.0.0 binding is blocked; typo'd --metrics flag value like 'localhost:99999'; port occupied by another monitoring agent.
Related errors
- --metrics has to be provided
- IPv6 bind address is specified, but edge-ip-version is IPv4
- expect IPv4, but %s is IPv6
- expect IPv6, but %s is IPv4
- Invalid IP %s
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/1cace4ffd864ba88.
Report an issue: GitHub.