valyala/fasthttp · error

too many transfer-encoding headers

Error message

too many transfer-encoding headers

What it means

fasthttp rejects a message that contains more than one Transfer-Encoding header. Duplicate Transfer-Encoding is a classic HTTP request smuggling vector, so the parser sets connectionClose and fails parsing instead of merging the headers. With secureErrorLogMessage enabled the public ErrUnsupportedTransferEncoding is returned instead of this detailed message.

Source

Thrown at header.go:3106

				continue
			}
			if caseInsensitiveCompare(s.key, strSetCookie) {
				h.cookies, kv = allocArg(h.cookies)
				kv.key = getCookieKey(kv.key, s.value)
				kv.value = append(kv.value[:0], s.value...)
				continue
			}
		case 't':
			if caseInsensitiveCompare(s.key, strTransferEncoding) {
				if h.noHTTP11 {
					continue
				}
				if transferEncodingSeen {
					h.connectionClose = true
					if h.secureErrorLogMessage {
						return 0, ErrUnsupportedTransferEncoding
					}
					return 0, errors.New("too many transfer-encoding headers")
				}
				transferEncodingSeen = true
				if !caseInsensitiveCompare(s.value, strChunked) {
					h.connectionClose = true
					if h.secureErrorLogMessage {
						return 0, ErrUnsupportedTransferEncoding
					}
					return 0, fmt.Errorf("unsupported transfer-encoding: %q", s.value)
				}
				h.contentLength = -1
				h.h = setArgBytes(h.h, strTransferEncoding, strChunked, argsHasValue)
				continue
			}
			if caseInsensitiveCompare(s.key, strTrailer) {
				err := h.SetTrailerBytes(s.value)
				if err != nil {
					h.connectionClose = true
					return 0, err

View on GitHub (pinned to c96f600972)

Solutions

  1. Fix or reject the offending client/proxy so only a single Transfer-Encoding: chunked header is sent.
  2. Ensure upstream proxies normalize Transfer-Encoding (remove duplicates before forwarding).
  3. Keep connectionClose behavior (fasthttp already closes the connection) and monitor logs for the source IP.
  4. If you own the sender code, set Transfer-Encoding only once via header.Set, not Add.

Example fix

// before
req.Header.Add("Transfer-Encoding", "chunked")
req.Header.Add("Transfer-Encoding", "chunked")
// after
req.Header.Set("Transfer-Encoding", "chunked")
Defensive patterns

Strategy: validation

Validate before calling

func hasSingleTransferEncoding(h map[string][]string) bool {
    return len(h["Transfer-Encoding"]) <= 1
}

Prevention

When it happens

Trigger: Parsing incoming request headers (tryReadHeaders/parseHeaders path at header.go:3106) when a second Transfer-Encoding header key is encountered after one was already seen.

Common situations: Malicious or buggy clients sending duplicated Transfer-Encoding headers; misconfigured proxies that append TE without removing the original; security scanners probing for request smuggling.

Related errors


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