valyala/fasthttp · warning
fasthttputil: connection closed
Error message
fasthttputil: connection closed
What it means
ErrConnectionClosed is returned by pipeConn Read/Write (and surfaced via httpConnError) when the in-memory pipe connection is closed — typically the peer hung up. fasthttputil documents it as indicating the underlying connection is closed, e.g. the client has disconnected.
Source
Thrown at fasthttputil/pipeconns.go:224
case <-c.pc.stopCh:
// rCh may contain data when stopCh is closed.
// Read the data before returning EOF.
select {
case c.b = <-c.rCh:
default:
return io.EOF
}
}
}
c.bb = c.b.b
return nil
}
var errWouldBlock = errors.New("would block")
// ErrConnectionClosed indicates that the underlying connection is closed. It could mean that the client has disconnected.
var ErrConnectionClosed = errors.New("fasthttputil: connection closed")
type timeoutError struct{}
func (e *timeoutError) Error() string {
return "fasthttputil: timeout"
}
// Timeout implements the Timeout method of the net.Error interface.
// This allows for checks like:
//
// if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
func (e *timeoutError) Timeout() bool {
return true
}
// ErrTimeout is returned from Read() or Write() on timeout.
var ErrTimeout = &timeoutError{}
View on GitHub (pinned to c96f600972)
Solutions
- Treat ErrConnectionClosed as EOF-equivalent in read loops and stop reading/writing
- Always Close the PipeConn on both sides when done to release blocked goroutines
- Retry with a fresh connection if the exchange must complete
- Avoid concurrent unsynchronized use of a single PipeConn
Example fix
// before
for {
n, err := conn.Read(buf)
if err != nil { log.Fatal(err) }
process(buf[:n])
}
// after
for {
n, err := conn.Read(buf)
if err != nil {
if err == fasthttputil.ErrConnectionClosed {
return // peer disconnected, normal EOF path
}
log.Fatal(err)
}
process(buf[:n])
} Defensive patterns
Strategy: try-catch
Type guard
func isConnClosed(err error) bool {
return errors.Is(err, fasthttputil.ErrConnectionClosed)
} Try / catch
n, err := pc.Read(buf)
if errors.Is(err, fasthttputil.ErrConnectionClosed) {
return io.EOF // treat as normal peer disconnect
} Prevention
- Treat ErrConnectionClosed as EOF in read loops
- Close both pipe ends when finished
- Don't share a PipeConn across goroutines unsynchronized
- Reconnect with a fresh PipeConn when needed
When it happens
Trigger: Writing to or reading from a fasthttputil.PipeConn after either endpoint called Close(); the writer side exits so the reader gets ErrConnectionClosed on subsequent reads; using the connection concurrently from multiple goroutines after shutdown.
Common situations: In-process client/server tests using InmemoryListener + PipeConn where one side finishes early; long-lived streaming pipes where the peer goroutine exits; forgetting that Read returns ErrConnectionClosed (not io.EOF) when the peer disconnects.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- fasthttp: the server closed connection before returning the
- fasthttp: no free connections available to host
- fasthttp: tls handshake timed out
- fasthttp: pipelined requests' queue has been overflowed. inc
- pipeline connection has been stopped
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/ab5cb0823cf044db.
Report an issue: GitHub.