istio/istio · critical
unable to listen on socket: %v
Error message
unable to listen on socket: %v
What it means
startMonitor binds istiod's monitoring HTTP endpoint with net.Listen("tcp", addr) — the addr from --monitoringAddr, default :15014. The listen syscall failed: the address is already in use, invalid, or the port is privileged/unavailable. It propagates up as "error initializing monitor" and istiod exits.
Source
Thrown at pilot/pkg/bootstrap/monitoring.go:87
http.Error(w, "Only requests from localhost are allowed", http.StatusForbidden)
return
}
// Pass control back to the handler
handler.ServeHTTP(w, r)
})
}
// Deprecated: we shouldn't have 2 http ports. Will be removed after code using
// this port is removed.
func startMonitor(exporter http.Handler, addr string, mux *http.ServeMux) (*monitor, error) {
m := &monitor{}
// get the network stuff setup
var listener net.Listener
if addr != "" {
var err error
if listener, err = net.Listen("tcp", addr); err != nil {
return nil, fmt.Errorf("unable to listen on socket: %v", err)
}
}
// NOTE: this is a temporary solution to provide bare-bones debug functionality
// for pilot. a full design / implementation of self-monitoring and reporting
// is coming. that design will include proper coverage of statusz/healthz type
// functionality, in addition to how pilot reports its own metrics.
addMonitor(exporter, mux)
if addr != "" {
m.monitoringServer = &http.Server{
Addr: listener.Addr().String(),
Handler: mux,
IdleTimeout: 90 * time.Second, // matches http.DefaultTransport keep-alive timeout
ReadTimeout: 30 * time.Second,
}
}
version.Info.RecordComponentBuildTag("pilot")View on GitHub (pinned to 8dc789c5cf)
Solutions
- Find the occupant on the node: ss -ltnp 'sport = :15014' (or kubectl describe pod to spot hostPort conflicts)
- Stop the duplicate process/pod holding the port
- Change --monitoringAddr to a free port, or set it empty to multiplex monitoring onto the httpAddr listener (server.go skips a dedicated listener when MonitoringAddr is empty)
- Fix a malformed --monitoringAddr value (must be host:port or :port)
Example fix
# before: port conflict -> "unable to listen on socket: listen tcp :15014: bind: address already in use" istiod --monitoringAddr=:15014 # another istiod already binds 15014 # after: move monitoring to a free port (or leave empty to share the HTTP listener) istiod --monitoringAddr=:15015
Defensive patterns
Strategy: validation
Validate before calling
// Reserve the monitoring port before istiod starts
func portFree(addr string) bool {
ln, err := net.Listen("tcp", addr)
if err != nil { return false }
_ = ln.Close()
return true
}
if !portFree(":15014") { return errors.New("monitoring port busy") } Prevention
- Avoid hostPort 15014 when multiple istiod replicas share a node
- Set --monitoringAddr to a free port or empty to multiplex on the HTTP listener
- Check ss -ltnp for port occupants before restarting istiod
When it happens
Trigger: Another process (a second istiod/pilot, an agent, a hostPort collision) already holds 15014; --monitoringAddr is malformed; the port is outside the allowed range in the container runtime.
Common situations: Duplicate istiod replicas on one node with hostPort 15014; sidecar or node exporters grabbing the port; leftover process from a crashed istiod; typo'd monitoring address flag.
Related errors
- error initializing debug server: %v
- error serving http: %v
- failed to start discovery service: %v
- error initializing monitor: %v
- could not setup exporter: %v
AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15).
Data as JSON: /api/errors/b7dabbf7f14d0a63.
Report an issue: GitHub.