valyala/fasthttp · error

unsupported http version %q in %q

Error message

unsupported http version %q in %q

What it means

The protocol token at the start of the response status line is not a recognizable HTTP version (HTTP/1.0, HTTP/1.1, etc.). fasthttp throws this, including the raw response, when the first line begins with something other than a valid HTTP version string.

Source

Thrown at header.go:2876

	}
	if len(statusCode) != 3 {
		if h.secureErrorLogMessage {
			return 0, ErrUnexpectedStatusCodeChar
		}
		return 0, fmt.Errorf("invalid response status code %q: response %q", statusCode, buf)
	}
	h.statusCode, n, err = parseUintBuf(statusCode)
	if err != nil || n != 3 {
		if h.secureErrorLogMessage {
			return 0, ErrUnexpectedStatusCodeChar
		}
		return 0, fmt.Errorf("invalid response status code %q: response %q", statusCode, buf)
	}
	if !isHTTPVersion(protoStr) {
		if h.secureErrorLogMessage {
			return 0, fmt.Errorf("unsupported http version %q", protoStr)
		}
		return 0, fmt.Errorf("unsupported http version %q in %q", protoStr, buf)
	}
	h.noHTTP11 = !bytes.Equal(protoStr, strHTTP11)
	h.protocol = append(h.protocol[:0], protoStr...)
	if len(statusMessage) > 0 {
		h.SetStatusMessage(statusMessage)
	}

	return len(buf) - len(bNext), nil
}

func isValidMethod(method []byte) bool {
	for _, ch := range method {
		if validMethodValueByteTable[ch] == 0 {
			return false
		}
	}
	return true
}

View on GitHub (pinned to c96f600972)

Solutions

  1. Verify the endpoint scheme and port with curl -v; use https:// plus a TLS-enabled fasthttp.Client if required
  2. Check you are not connecting to a non-HTTP service on that port
  3. If the server requires HTTP/2, use a client that supports it (net/http with ForceAttemptHTTP2) instead of fasthttp
  4. Inspect the echoed %q response body to identify exactly what the peer sent

Example fix

// before
fasthttp.Get(nil, "http://example.com:443/")
// after
fasthttp.Get(nil, "https://example.com/")
Defensive patterns

Strategy: try-catch

Validate before calling

resp, err := http.Get(url) // sanity check endpoint speaks HTTP with std client first
if err != nil { return err }
resp.Body.Close()

Type guard

func isUnsupportedHTTPVersion(err error) bool {
    return err != nil && strings.Contains(err.Error(), "unsupported http version in")
}

Try / catch

err := client.Do(req, resp)
if err != nil && strings.Contains(err.Error(), "unsupported http version") {
    log.Error("peer is not speaking HTTP/1.x", "endpoint", req.URI(), "err", err)
    return errBadUpstream
}

Prevention

When it happens

Trigger: ResponseHeader.parseFirstLine: bytes.IndexByte found a space, but b[:n] (protoStr) fails isHTTPVersion — e.g. response starts with '<html>', 'SSH-2.0', or TLS alert bytes.

Common situations: Speaking plain HTTP to an HTTPS-only port (receiving TLS binary), hitting an SSH/SMTP/HTML service, DNS or firewall interstitials, HTTP/2 prior-knowledge endpoints that reject HTTP/1.1 framing.

Related errors


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