ginuerzh/gost · error
accpet on closed listener
Error message
accpet on closed listener
What it means
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.
Source
Thrown at udp.go:142
select {
case conn.rChan <- b[:n]:
if Debug {
log.Logf("[udp] %s >>> %s : length %d", raddr, l.Addr(), n)
}
default:
log.Logf("[udp] %s -> %s : recv queue is full (%d)", raddr, l.Addr(), cap(conn.rChan))
}
}
}
func (l *udpListener) Accept() (conn net.Conn, err error) {
var ok bool
select {
case conn = <-l.connChan:
case err, ok = <-l.errChan:
if !ok {
err = errors.New("accpet on closed listener")
}
}
return
}
func (l *udpListener) Addr() net.Addr {
return l.ln.LocalAddr()
}
func (l *udpListener) Close() error {
err := l.ln.Close()
l.connMap.Range(func(k interface{}, v *udpServerConn) bool {
v.Close()
return true
})
return err
}View on GitHub (pinned to a33fdbf4c9)
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.
Example fix
// before
for {
conn, err := l.Accept()
if err != nil {
log.Println(err) // keeps looping or logs noise
continue
}
}
// after
for {
conn, err := l.Accept()
if err != nil {
return // exit accept loop on closed listener
}
}
Defensive patterns
Strategy: type-guard
Validate before calling
var open atomic.Bool
// set open.Store(true) after listener creation, false after Close
if !open.Load() { return errors.New("listener already shut down") } Type guard
func isAcceptClosedErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "closed listener")
} Try / catch
conn, err := l.Accept()
if err != nil {
if isAcceptClosedErr(err) { return nil } // clean shutdown
log.Printf("accept: %v", err)
continue
} Prevention
- 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.
When it happens
Trigger: Calling Accept on a *udpListener after Close() has been called; a serve loop continuing to Accept while another goroutine shuts the listener down.
Common situations: Server accept loops racing with graceful shutdown; forgetting to exit the accept goroutine before closing the listener; reusing a closed listener after connection errors.
Related errors
- accpet on closed listener
- accept on closed listener
- accpet on closed listener
- read from closed connection
- connection is closed
AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02).
Data as JSON: /api/errors/9229284312e6c1be.
Report an issue: GitHub.