valyala/fasthttp · error

fasthttp: the server closed connection before returning the

Error message

fasthttp: the server closed connection before returning the first response byte. make sure the server returns 'connection: close' response header before closing the connection

What it means

ErrConnectionClosed is returned when the server closes the connection before returning the first response byte. fasthttp retries idempotent requests automatically; for non-idempotent ones it surfaces this error and advises fixing keep-alive semantics on either side.

Source

Thrown at client.go:1796

	return c.Transport
}

var (
	// ErrNoFreeConns is returned when no free connections available
	// to the given host.
	//
	// Increase the allowed number of connections per host if you
	// see this error.
	ErrNoFreeConns = errors.New("fasthttp: no free connections available to host")

	// ErrConnectionClosed may be returned from client methods if the server
	// closes connection before returning the first response byte.
	//
	// If you see this error, then either fix the server by returning
	// 'Connection: close' response header before closing the connection
	// or add 'Connection: close' request header before sending requests
	// to broken server.
	ErrConnectionClosed = errors.New("fasthttp: the server closed connection before returning the first response byte. " +
		"make sure the server returns 'connection: close' response header before closing the connection")

	// ErrConnPoolStrategyNotImpl is returned when HostClient.ConnPoolStrategy is not implement yet.
	// If you see this error, then you need to check your HostClient configuration.
	ErrConnPoolStrategyNotImpl = errors.New("fasthttp: connection pool strategy is not implement")
)

type timeoutError struct{}

func (e *timeoutError) Error() string {
	return "fasthttp: timeout"
}

// Timeout implements the Timeout behavior 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 {

View on GitHub (pinned to c96f600972)

Solutions

  1. Make the server send 'Connection: close' before closing, or align its idle timeout above the client's MaxIdleConnDuration
  2. Set the request header 'Connection: close' when talking to a known-broken server
  3. Configure Client.RetryIf to also retry ErrConnectionClosed for safe operations
  4. Shorten Client.MaxIdleConnDuration so the client discards idle conns before the server does

Example fix

// before
req.Header.SetMethod(fasthttp.MethodPost) // non-idempotent, no retry on closed conn
// after
req.Header.Set("Connection", "close") // or:
client.RetryIf = func(_ *fasthttp.Request, _ *fasthttp.Response, err error) bool {
    return errors.Is(err, fasthttp.ErrConnectionClosed)
}
Defensive patterns

Strategy: retry

Validate before calling

// keep client idle conns shorter-lived than the server's keep-alive timeout
client.MaxIdleConnDuration = serverKeepAliveTimeout - 5*time.Second

Try / catch

if errors.Is(err, fasthttp.ErrConnectionClosed) {
    return do(req, resp) // safe only if the operation is idempotent
}

Prevention

When it happens

Trigger: Server keep-alive idle timeout elapses and the connection is closed just as the client sends a new request; non-idempotent (POST) requests are not retried so the error escapes; server restart/crash mid-request.

Common situations: Behind load balancers with short idle timeouts; servers closing idle conns; POST requests hitting a pooled connection that was reaped; frequent deploy restarts.

Related errors


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/942dafc69a451402. Report an issue: GitHub.