{"record":{"id":"da67823891081fb4","repo":"nsqio/nsq","slug":"listen-s-failed-s","errorCode":null,"errorMessage":"listen (%s) failed - %s","messagePattern":"listen \\((.+?)\\) failed - (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"nsqadmin/nsqadmin.go","lineNumber":120,"sourceCode":"\t\t}\n\t\tn.graphiteURL = url\n\t}\n\n\tif opts.AllowConfigFromCIDR != \"\" {\n\t\t_, _, err := net.ParseCIDR(opts.AllowConfigFromCIDR)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse --allow-config-from-cidr (%s) - %s\", opts.AllowConfigFromCIDR, err)\n\t\t}\n\t}\n\n\topts.BasePath = normalizeBasePath(opts.BasePath)\n\n\tn.logf(LOG_INFO, version.String(\"nsqadmin\"))\n\n\tvar err error\n\tn.httpListener, err = net.Listen(\"tcp\", n.getOpts().HTTPAddress)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"listen (%s) failed - %s\", n.getOpts().HTTPAddress, err)\n\t}\n\n\treturn n, nil\n}\n\nfunc normalizeBasePath(p string) string {\n\tif len(p) == 0 {\n\t\treturn \"/\"\n\t}\n\t// add leading slash\n\tif p[0] != '/' {\n\t\tp = \"/\" + p\n\t}\n\treturn path.Clean(p)\n}\n\nfunc (n *NSQAdmin) getOpts() *Options {\n\treturn n.opts.Load().(*Options)","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/nsqio/nsq/blob/85cf10c09c6c3c86160d6f0eb156f62d0efc1648/nsqadmin/nsqadmin.go#L102-L138","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\n--http-address=0.0.0.0:4171   # port already in use by another nsqadmin\n\n# after\n--http-address=0.0.0.0:4172","handlingStrategy":"try-catch","validationCode":"// probe before full startup\nln, err := net.Listen(\"tcp\", opts.HTTPAddress)\nif err != nil {\n\tlog.Fatalf(\"address %s not bindable: %v\", opts.HTTPAddress, err)\n}\nln.Close()","typeGuard":"func isAddrInUse(err error) bool {\n\tif errors.Is(err, syscall.EADDRINUSE) {\n\t\treturn true\n\t}\n\tvar opErr *net.OpError\n\treturn errors.As(err, &opErr) && errors.Is(opErr.Err, syscall.EADDRINUSE)\n}","tryCatchPattern":"n, err := nsqadmin.New(opts)\nif err != nil {\n\tif isAddrInUse(err) {\n\t\t// port held: free it or pick another port, then restart (do not loop tightly)\n\t}\n\tlog.Fatal(err)\n}","preventionTips":["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"],"tags":["nsqadmin","network","bind","port-in-use","startup"],"backgroundTag":null,"analyzedSha":"85cf10c09c6c3c86160d6f0eb156f62d0efc1648","analyzedAt":"2026-08-16T00:53:05.009Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}