ginuerzh/gost · error

accpet on closed listener

Error message

accpet on closed listener

What it means

quicListener.Accept returns this error when the listener's error channel is closed, meaning the underlying QUIC listener has been shut down. The channel-closed signal is converted into an explicit error so callers can distinguish 'listener closed' from a real accept failure.

Source

Thrown at quic.go:239

		}

		cc := &quicConn{Stream: stream, laddr: session.LocalAddr(), raddr: session.RemoteAddr()}
		select {
		case l.connChan <- cc:
		default:
			cc.Close()
			log.Logf("[quic] %s - %s: connection queue is full", session.RemoteAddr(), session.LocalAddr())
		}
	}
}

func (l *quicListener) 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 *quicListener) Addr() net.Addr {
	return l.ln.Addr()
}

func (l *quicListener) Close() error {
	return l.ln.Close()
}

type quicConn struct {
	quic.Stream
	laddr net.Addr
	raddr net.Addr
}

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Stop the Accept loop when this error is returned (standard pattern: return from the accept goroutine)
  2. Ensure Close() is only called once and that shutdown logic terminates accept loops
  3. If you didn't intend to close, find what closed the listener (supervisor, signal handler, parent context)

Example fix

// before
for {
    conn, err := l.Accept()
    if err != nil { log.Log(err); continue } // infinite loop on closed listener
    go handle(conn)
}
// after
for {
    conn, err := l.Accept()
    if err != nil { return } // stop looping when listener is closed
    go handle(conn)
}
Defensive patterns

Strategy: try-catch

Try / catch

conn, err := l.Accept()
if err != nil {
    // listener closed or fatal accept error: stop the accept loop
    return
}

Prevention

When it happens

Trigger: Calling Accept on a quicListener after Close() has been invoked (which closes l.errChan), so the select receives the zero error with ok == false.

Common situations: Accept loops that keep running after the server was shut down; a race between Close() and a pending/next Accept call in a connection-handling goroutine.

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/80fbcbda7d1937c8. Report an issue: GitHub.