nats-io/nats-server · error

can't listen to the monitor port

Error message

can't listen to the monitor port: %v

What it means

The monitoring listener could not be bound: net.Listen("tcp", host:port) failed and the underlying OS error is wrapped. Typical causes are the port already in use, permission denied for privileged ports, or an unbindable host address.

Solutions

  1. Check and free the port: `lsof -i :8222` / `ss -ltnp`, stop the conflicting process or pick another port
  2. Bind to 0.0.0.0 or the loopback interface instead of an unresolvable host in `http_host`
  3. For ports <1024 run with the required capability/root or choose a high port
  4. Read the wrapped `%v` OS error to distinguish address-in-use vs permission vs no-route

Example fix

// before
http_host: "myhost.internal"
http_port: 8222
// after
http_host: "0.0.0.0"
http_port: 8222
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check that the monitor port is bindable before starting the server
func portFree(host string, port int) error {
    ln, err := net.Listen("tcp", net.JoinHostPort(host, strconv.Itoa(port)))
    if err != nil { return err }
    return ln.Close()
}

Try / catch

if err := srv.StartMonitoring(); err != nil {
    var wrapped string = err.Error()
    if strings.Contains(wrapped, "can't listen to the monitor port") {
        if strings.Contains(wrapped, "address already in use") {
            log.Print("monitor port taken: stop the other process or change http_port")
        } else if strings.Contains(wrapped, "permission denied") {
            log.Print("use a port >1024 or grant CAP_NET_BIND_SERVICE")
        }
    }
    return err
}

Prevention

When it happens

Trigger: startMonitoring calls net.Listen for opts.HTTPPort/HTTPSPort (or the randomly allocated port) on opts.HTTPHost; any listen error (EADDRINUSE, EACCES, invalid host) triggers this.

Common situations: Another nats-server or old instance still holding 8222; binding to a hostname that doesn't resolve to a local interface; port <1024 without root; container missing CAP_NET_BIND_SERVICE.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/73d8a4b8fabfabdd. Report an issue: GitHub.

Appendix: source

Thrown at server/server.go:3140

		hp = net.JoinHostPort(opts.HTTPHost, strconv.Itoa(port))
		config := opts.TLSConfig.Clone()
		if !s.ocspPeerVerify {
			config.GetConfigForClient = s.getMonitoringTLSConfig
			config.ClientAuth = tls.NoClientCert
		}
		httpListener, err = tls.Listen("tcp", hp, config)

	} else {
		port = opts.HTTPPort
		if port == -1 {
			port = 0
		}
		hp = net.JoinHostPort(opts.HTTPHost, strconv.Itoa(port))
		httpListener, err = net.Listen("tcp", hp)
	}

	if err != nil {
		return fmt.Errorf("can't listen to the monitor port: %v", err)
	}

	rport := httpListener.Addr().(*net.TCPAddr).Port
	s.Noticef("Starting %s monitor on %s", monitorProtocol, net.JoinHostPort(opts.HTTPHost, strconv.Itoa(rport)))

	mux := http.NewServeMux()

	// Root
	mux.HandleFunc(s.basePath(RootPath), s.HandleRoot)
	// Varz
	mux.HandleFunc(s.basePath(VarzPath), s.HandleVarz)
	// Connz
	mux.HandleFunc(s.basePath(ConnzPath), s.HandleConnz)
	// Routez
	mux.HandleFunc(s.basePath(RoutezPath), s.HandleRoutez)
	// Gatewayz
	mux.HandleFunc(s.basePath(GatewayzPath), s.HandleGatewayz)
	// Leafz

View on GitHub (pinned to 3a66a489d2)