{"record":{"id":"60ba241a6de4af8d","repo":"nsqio/nsq","slug":"listener-accept-error-s","errorCode":null,"errorMessage":"listener.Accept() error - %s","messagePattern":"listener\\.Accept\\(\\) error - (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/protocol/tcp_server.go","lineNumber":34,"sourceCode":"\nfunc TCPServer(listener net.Listener, handler TCPHandler, logf lg.AppLogFunc) error {\n\tlogf(lg.INFO, \"TCP: listening on %s\", listener.Addr())\n\n\tvar wg sync.WaitGroup\n\n\tfor {\n\t\tclientConn, err := listener.Accept()\n\t\tif err != nil {\n\t\t\t// net.Error.Temporary() is deprecated, but is valid for accept\n\t\t\t// this is a hack to avoid a staticcheck error\n\t\t\tif te, ok := err.(interface{ Temporary() bool }); ok && te.Temporary() {\n\t\t\t\tlogf(lg.WARN, \"temporary Accept() failure - %s\", err)\n\t\t\t\truntime.Gosched()\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// theres no direct way to detect this error because it is not exposed\n\t\t\tif !errors.Is(err, net.ErrClosed) {\n\t\t\t\treturn fmt.Errorf(\"listener.Accept() error - %s\", err)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\twg.Add(1)\n\t\tgo func() {\n\t\t\thandler.Handle(clientConn)\n\t\t\twg.Done()\n\t\t}()\n\t}\n\n\t// wait to return until all handler goroutines complete\n\twg.Wait()\n\n\tlogf(lg.INFO, \"TCP: closing %s\", listener.Addr())\n\n\treturn nil\n}","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/nsqio/nsq/blob/85cf10c09c6c3c86160d6f0eb156f62d0efc1648/internal/protocol/tcp_server.go#L16-L52","documentation":"internal/protocol.TCPServer (internal/protocol/tcp_server.go) is the accept loop behind nsqd's 4150 and nsqlookupd's 4160 TCP ports. Temporary accept errors (net.Error.Temporary) are logged as warnings and retried after a Gosched; a 403-like ErrClosed from listener.Close during shutdown breaks the loop cleanly. Any other accept error is wrapped as 'listener.Accept() error - %s' and returned, terminating the TCP serving goroutine and, via main's error handling, the process.","triggerScenarios":"Accept() failing with a non-temporary, non-ErrClosed error: fd exhaustion that the runtime no longer classifies as temporary, ENFILE/ENOMEM system-wide, a listener fd invalidated underneath the process (hot socket transfer done wrong, container socket passthrough), or EBADF after a buggy external Close. Deliberate shutdown does NOT trigger this — Close produces net.ErrClosed which is filtered.","commonSituations":"Hosts exhausting file descriptors because of connection churn or leaked conns from misbehaving clients; exotic socket managers (systemd socket activation with wrong settings, sidecar proxies) handing over bad fds; OS-level limits (fs.file-max) hit during traffic spikes; running under old runtimes with different Temporary() semantics.","solutions":["Read the wrapped syscall text: 'too many open files' -> raise ulimit -n / LimitNOFILE and check /proc/<pid>/fd for leaks; other errnos point to the socket manager.","Restart the process once limits are fixed; the error is fatal to the daemon by design.","Audit for fd leaks: 'ls /proc/<pid>/fd | wc -l' over time; ensure clients (especially broken custom ones) close connections.","If using socket activation/proxies, test plain binding first to rule out fd handoff problems."],"exampleFix":"# before\n# nsqd: listener.Accept() error - accept tcp 0.0.0.0:4150: accept4: too many open files\nulimit -n 1024\n\n# after\n# raise limits and restart\nulimit -n 65536   # or systemd LimitNOFILE=65536\nsystemctl restart nsqd","handlingStrategy":"retry","validationCode":"// pre-flight: ensure the TCP port is bindable before daemon start\nln, err := net.Listen(\"tcp\", addr)\nif err != nil {\n    return fmt.Errorf(\"cannot bind %s: %w\", addr, err)\n}\nln.Close() // release; the daemon binds next","typeGuard":null,"tryCatchPattern":"// TCPServer's return is fatal by design; supervisors should catch, classify, restart\nif err := protocol.TCPServer(ln, &prot); err != nil && !errors.Is(err, net.ErrClosed) {\n    log.Printf(\"tcp accept loop died: %v\", err)\n    if strings.Contains(err.Error(), \"too many open files\") {\n        bumpFDLimitThenRestart()\n    } else {\n        restart()\n    }\n}","preventionTips":["Raise ulimit -n / LimitNOFILE on hosts running nsqd/nsqlookupd.","Watch /proc/<pid>/fd growth to catch conn leaks early.","Avoid external socket handoff tools unless tested against this loop."],"tags":["tcp","server","accept","fatal","file-descriptors","nsqd"],"backgroundTag":null,"analyzedSha":"85cf10c09c6c3c86160d6f0eb156f62d0efc1648","analyzedAt":"2026-08-16T00:53:05.009Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}