valyala/fasthttp · error

unsupported transfer-encoding: %q

Error message

unsupported transfer-encoding: %q

What it means

fasthttp rejects a Transfer-Encoding header whose value is not 'chunked' (case-insensitive). RFC 7230 only allows 'chunked' as the final transfer coding, so any other value makes the message framing unparseable and fasthttp closes the connection (connectionClose=true). When secureErrorLogMessage is enabled the sentinel ErrUnsupportedTransferEncoding is returned instead of the value-embedding message.

Source

Thrown at header.go:3114

		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
				}
				continue
			}
		}
		h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue)
	}

	if s.err != nil {

View on GitHub (pinned to c96f600972)

Solutions

  1. Remove the Transfer-Encoding header and send the body with Content-Length instead, or use exactly 'Transfer-Encoding: chunked'.
  2. If the intent is compression, set Content-Encoding: gzip on the body, not Transfer-Encoding.
  3. Fix the upstream client/proxy that emits the non-chunked transfer coding.
  4. If you control the server and only need to avoid echoing header values in logs, set Server.SecureErrorLogMessage to get the sanitized error.

Example fix

// before (client hand-rolled request)
req.Header.Set("Transfer-Encoding", "gzip")
// after
req.Header.Set("Content-Encoding", "gzip")
req.Header.Set("Transfer-Encoding", "chunked")
Defensive patterns

Strategy: validation

Validate before calling

func validTransferEncoding(te string) bool {
    return strings.EqualFold(strings.TrimSpace(te), "chunked") || te == ""
}
// check before sending: if !validTransferEncoding(te) { fix or drop header }

Try / catch

var errUnsupportedTE = errors.New("unsupported transfer-encoding")
if err := server.ServeConn(...); err != nil && strings.Contains(err.Error(), "unsupported transfer-encoding") {
    // close connection / return 400 to client
}

Prevention

When it happens

Trigger: Parsing a request/response whose Transfer-Encoding header is set to something other than 'chunked' or 'identity'-style values — e.g. 'Transfer-Encoding: gzip', 'compress', 'deflate', or a malformed multi-value like 'chunked, gzip' in the wrong order.

Common situations: Proxies or clients behind middleware that compresses bodies and rewrites headers; hand-rolled HTTP clients setting Transfer-Encoding instead of Content-Encoding; misconfigured load balancers adding transfer codings.

Related errors


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