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

  1. Check what is using the metrics port (lsof -i :<port> / netstat) and stop the conflicting process.
  2. 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.
  3. Disable metrics entirely with --metrics none if scraping is not needed.
  4. 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

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


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/1cace4ffd864ba88. Report an issue: GitHub.