valyala/fasthttp · error

fasthttp: hostclient can't follow redirects to a different p

Error message

fasthttp: hostclient can't follow redirects to a different protocol, please use client instead

What it means

ErrHostClientRedirectToDifferentScheme is returned when a HostClient follows a redirect whose Location targets a different protocol (e.g. an https-bound HostClient redirected to http, or vice versa). HostClient is pinned to one scheme, so it cannot serve the redirect target; the general fasthttp.Client must be used instead.

Source

Thrown at client.go:1233

	statusCode, body, err = doRequestFollowRedirectsBuffer(req, dst, url, c)

	return statusCode, body, err
}

var (
	// ErrMissingLocation is returned by clients when the Location header is missing on
	// an HTTP response with a redirect status code.
	ErrMissingLocation = errors.New("fasthttp: missing location header for http redirect")
	// ErrTooManyRedirects is returned by clients when the number of redirects followed
	// exceed the max count.
	ErrTooManyRedirects = errors.New("fasthttp: too many redirects detected when doing the request")
	// ErrRedirectBodyStream is returned by clients when a redirect that keeps the request
	// body is received for a request whose body is a stream. The hop that produced the
	// redirect consumed the stream, so the body cannot be sent again.
	ErrRedirectBodyStream = errors.New("fasthttp: cannot follow a body-preserving redirect for a request with a body stream")

	// ErrHostClientRedirectToDifferentScheme is returned when a HostClient follows a redirect to a different protocol.
	ErrHostClientRedirectToDifferentScheme = errors.New("fasthttp: hostclient can't follow redirects to a different protocol," +
		" please use client instead")
)

const defaultMaxRedirectsCount = 16

// Only drain response streams that are known to be small. Reading an unknown
// length stream can block forever (for example, on an event stream), while
// closing a large stream avoids transferring a body the caller discarded.
const maxResponseBodyDrainSize = 8 * 1024

func closeOrDrainResponseBody(resp *Response, maxDrainSize int) error {
	if !resp.IsBodyStream() {
		return nil
	}

	contentLength := resp.Header.ContentLength()
	if contentLength < 0 || contentLength > maxDrainSize {
		return resp.CloseBodyStream()

View on GitHub (pinned to c96f600972)

Solutions

  1. Switch to fasthttp.Client and use DoRedirects, which handles both schemes
  2. Fix the server so redirects keep the same scheme (force https consistently)
  3. Normalize the redirect Location on a proxy before it reaches the client
  4. If you must keep HostClient, resolve the redirect target manually and use a second client for the other scheme

Example fix

// before
hc := &fasthttp.HostClient{Addr: "example.com:443", IsTLS: true}
// hc.DoRedirects -> ErrHostClientRedirectToDifferentScheme on http Location
// after
c := &fasthttp.Client{}
_, _, err := c.DoRedirects(req, resp) // follows cross-scheme redirects
Defensive patterns

Strategy: validation

Validate before calling

loc := string(resp.Header.Peek(fasthttp.HeaderLocation))
if loc != "" && strings.HasPrefix(loc, "http://") == hc.IsTLS {
    // cross-scheme redirect coming; use fasthttp.Client instead
}

Try / catch

if errors.Is(err, fasthttp.ErrHostClientRedirectToDifferentScheme) {
    // re-issue the request via fasthttp.Client{} DoRedirects
}

Prevention

When it happens

Trigger: HostClient with IsTLS set (https) receiving a 3xx whose Location begins with http:// (or the inverse); any redirect chain crossing scheme boundaries.

Common situations: Services redirecting to login pages on another scheme; mixed http/https behind a load balancer; servers redirecting https traffic back to plain http.

Related errors


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