hashicorp/nomad · critical

failed to start HTTP listener: %v

Error message

failed to start HTTP listener: %v

What it means

Returned by NewHTTPServers (command/agent/http.go:192) when config.Listener fails to open a TCP listener for one of the agent's HTTP addresses. The error is appended to a multierror and that listener skipped; startup fails only if no listener can be created.

Source

Thrown at command/agent/http.go:192

	// Enable HTTP2 unless it has been disabled in the configuration.
	if !config.HTTPDisableHTTP2 {
		protocols.SetHTTP2(true)
		// If TLS is not enabled for HTTP, make HTTP2 available over cleartext.
		if !config.TLSConfig.EnableHTTP {
			protocols.SetUnencryptedHTTP2(true)
		}
	}

	// Start the listener
	for _, addr := range config.normalizedAddrs.HTTP {
		lnAddr, err := net.ResolveTCPAddr("tcp", addr)
		if err != nil {
			serverInitializationErrors = multierror.Append(serverInitializationErrors, err)
			continue
		}
		ln, err := config.Listener("tcp", lnAddr.IP.String(), lnAddr.Port)
		if err != nil {
			serverInitializationErrors = multierror.Append(serverInitializationErrors, fmt.Errorf("failed to start HTTP listener: %v", err))
			continue
		}

		// If TLS is enabled, wrap the listener with a TLS listener
		if config.TLSConfig.EnableHTTP {
			tlsConfig, err := tlsConf.IncomingTLSConfig()
			if err != nil {
				serverInitializationErrors = multierror.Append(serverInitializationErrors, err)
				continue
			}
			if !config.HTTPDisableHTTP2 {
				tlsConfig.NextProtos = []string{ProtoHttp2}
			}
			ln = tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, tlsConfig)
		}

		// Create the server
		srv := &HTTPServer{

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Find and stop the conflicting process (lsof -i :4646 / ss -ltnp) or change `ports { http = ... }` to a free port.
  2. Ensure the configured bind address exists on the host interface.
  3. Use a non-privileged port or grant the required capability for ports <1024.
  4. If it occurred during reload, verify addresses in the new config and reload again.

Example fix

// before (HCL)
ports {
  http = 4646
}
// after (move off the occupied port)
ports {
  http = 14646
}
Defensive patterns

Strategy: try-catch

Validate before calling

addr := &net.TCPAddr{IP: net.ParseIP(bindIP), Port: httpPort}
ln, err := net.Listen("tcp", addr.String())
if err != nil {
    return fmt.Errorf("http port %d unavailable: %v", httpPort, err)
}
ln.Close()

Try / catch

if err := agent.Setup(); err != nil {
    if strings.Contains(err.Error(), "failed to start HTTP listener") {
        // check lsof -i :4646 for a conflicting process, change ports, retry
    }
}

Prevention

When it happens

Trigger: Binding a port already in use by another process or agent, binding to an IP not present on the host, lacking privilege for ports <1024, or bad address syntax in bind_addr/ports during start or HTTP reload.

Common situations: Two agents on one host; a crashed leftover process holding 4646; containers sharing host networking; bind address changed to an IP that no longer exists; SELinux/AppArmor blocking bind.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/5ab54f45fb6e77d1. Report an issue: GitHub.