nsqio/nsq · critical
listen (%s) failed - %s
Error message
listen (%s) failed - %s
What it means
nsqadmin.New binds its HTTP listener with net.Listen("tcp", HTTPAddress) (the --http-address flag, default 0.0.0.0:4171). The returned error is wrapped as 'listen (%s) failed' and the process cannot start. Almost always this is the port already being held or the address being unbindable.
Source
Thrown at nsqadmin/nsqadmin.go:120
}
n.graphiteURL = url
}
if opts.AllowConfigFromCIDR != "" {
_, _, err := net.ParseCIDR(opts.AllowConfigFromCIDR)
if err != nil {
return nil, fmt.Errorf("failed to parse --allow-config-from-cidr (%s) - %s", opts.AllowConfigFromCIDR, err)
}
}
opts.BasePath = normalizeBasePath(opts.BasePath)
n.logf(LOG_INFO, version.String("nsqadmin"))
var err error
n.httpListener, err = net.Listen("tcp", n.getOpts().HTTPAddress)
if err != nil {
return nil, fmt.Errorf("listen (%s) failed - %s", n.getOpts().HTTPAddress, err)
}
return n, nil
}
func normalizeBasePath(p string) string {
if len(p) == 0 {
return "/"
}
// add leading slash
if p[0] != '/' {
p = "/" + p
}
return path.Clean(p)
}
func (n *NSQAdmin) getOpts() *Options {
return n.opts.Load().(*Options)View on GitHub (pinned to 85cf10c09c)
Solutions
- Find and stop the holder: lsof -i :4171 or ss -ltnp | grep 4171, then restart nsqadmin
- Pick a different port via --http-address=0.0.0.0:4172 (or :4172 for all interfaces)
- Use a fully qualified host:port (127.0.0.1:4171) and bracket IPv6 literals ([::1]:4171)
- For ports <1024, run under a capability-granting unit (AmbientCapabilities=CAP_NET_BIND_SERVICE) instead of root
Example fix
# before --http-address=0.0.0.0:4171 # port already in use by another nsqadmin # after --http-address=0.0.0.0:4172
Defensive patterns
Strategy: try-catch
Validate before calling
// probe before full startup
ln, err := net.Listen("tcp", opts.HTTPAddress)
if err != nil {
log.Fatalf("address %s not bindable: %v", opts.HTTPAddress, err)
}
ln.Close() Type guard
func isAddrInUse(err error) bool {
if errors.Is(err, syscall.EADDRINUSE) {
return true
}
var opErr *net.OpError
return errors.As(err, &opErr) && errors.Is(opErr.Err, syscall.EADDRINUSE)
} Try / catch
n, err := nsqadmin.New(opts)
if err != nil {
if isAddrInUse(err) {
// port held: free it or pick another port, then restart (do not loop tightly)
}
log.Fatal(err)
} Prevention
- Reserve the nsqadmin port per host in your inventory
- Use distinct ports when running multiple admin instances on one box
- Set systemd restart backoff so overlapping restarts do not fight over the socket
When it happens
Trigger: Another nsqadmin (or any process) already bound 4171; a privileged port (<1024) chosen while running as non-root; malformed --http-address (missing port, bad host literal, e.g. 'localhost' without ':4171'); IPv6 literal not in brackets; firewall/SELinux denying the bind.
Common situations: Running two nsqadmin instances with the same flags; a container without distinct port mappings; systemd restart racing a socket held by a dying process; switching from 0.0.0.0:4171 to a specific interface IP that no longer exists on the host.
Related errors
- listen (%s) failed - %s
- listen (%s) failed - %s
- failed to LoadX509KeyPair %s, %s - %s
- failed to read TLS root CA file %s - %s
- failed to AppendCertsFromPEM %s
AI-assisted analysis of nsqio/nsq@85cf10c09c (2026-08-16).
Data as JSON: /api/errors/da67823891081fb4.
Report an issue: GitHub.