{"record":{"id":"9229284312e6c1be","repo":"ginuerzh/gost","slug":"accpet-on-closed-listener-922928","errorCode":null,"errorMessage":"accpet on closed listener","messagePattern":"accpet on closed listener","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"udp.go","lineNumber":142,"sourceCode":"\n\t\tselect {\n\t\tcase conn.rChan <- b[:n]:\n\t\t\tif Debug {\n\t\t\t\tlog.Logf(\"[udp] %s >>> %s : length %d\", raddr, l.Addr(), n)\n\t\t\t}\n\t\tdefault:\n\t\t\tlog.Logf(\"[udp] %s -> %s : recv queue is full (%d)\", raddr, l.Addr(), cap(conn.rChan))\n\t\t}\n\t}\n}\n\nfunc (l *udpListener) Accept() (conn net.Conn, err error) {\n\tvar ok bool\n\tselect {\n\tcase conn = <-l.connChan:\n\tcase err, ok = <-l.errChan:\n\t\tif !ok {\n\t\t\terr = errors.New(\"accpet on closed listener\")\n\t\t}\n\t}\n\treturn\n}\n\nfunc (l *udpListener) Addr() net.Addr {\n\treturn l.ln.LocalAddr()\n}\n\nfunc (l *udpListener) Close() error {\n\terr := l.ln.Close()\n\tl.connMap.Range(func(k interface{}, v *udpServerConn) bool {\n\t\tv.Close()\n\t\treturn true\n\t})\n\n\treturn err\n}","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/ginuerzh/gost/blob/a33fdbf4c98034f4bfeeaea9868909822b9c526d/udp.go#L124-L160","documentation":"udpListener.Accept returns this error when the listener's errChan is closed, which happens during listener shutdown. It indicates Accept was invoked on a UDP listener that has already been closed; the typo 'accpet' is part of the message itself.","triggerScenarios":"Calling Accept on a *udpListener after Close() has been called; a serve loop continuing to Accept while another goroutine shuts the listener down.","commonSituations":"Server accept loops racing with graceful shutdown; forgetting to exit the accept goroutine before closing the listener; reusing a closed listener after connection errors.","solutions":["Stop the Accept loop when this error is returned — it signals the listener is closed and will not accept again.","Close the listener only after the accept goroutine has exited, or coordinate shutdown with a WaitGroup/context.","Match the error (or use errors.Is on a stored sentinel) and treat it as io.ErrClosedPipe/io.EOF equivalent to terminate cleanly."],"exampleFix":"// before\nfor {\n    conn, err := l.Accept()\n    if err != nil {\n        log.Println(err) // keeps looping or logs noise\n        continue\n    }\n}\n// after\nfor {\n    conn, err := l.Accept()\n    if err != nil {\n        return // exit accept loop on closed listener\n    }\n}\n","handlingStrategy":"type-guard","validationCode":"var open atomic.Bool\n// set open.Store(true) after listener creation, false after Close\nif !open.Load() { return errors.New(\"listener already shut down\") }","typeGuard":"func isAcceptClosedErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"closed listener\")\n}","tryCatchPattern":"conn, err := l.Accept()\nif err != nil {\n    if isAcceptClosedErr(err) { return nil } // clean shutdown\n    log.Printf(\"accept: %v\", err)\n    continue\n}","preventionTips":["Exit the accept loop on any Accept error for UDP listeners.","Shut down via context: cancel context first, then close the listener, then wait for accept goroutine.","Use a WaitGroup to join the serve loop before process exit.","Don't attempt to reuse a closed listener."],"tags":["udp","listener","accept","closed-listener","network"],"backgroundTag":"listener-closed","analyzedSha":"a33fdbf4c98034f4bfeeaea9868909822b9c526d","analyzedAt":"2026-09-02T22:15:54.506Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}