valyala/fasthttp · error
fasthttp: duplicate content-length header
Error message
fasthttp: duplicate content-length header
What it means
HTTP messages must carry at most one Content-Length header. When parsing headers fasthttp detects a second Content-Length and returns ErrDuplicateContentLength, since duplicates can desynchronize body framing and are a classic request-smuggling vector. The error surfaces from Response/Request Read header parsing.
Source
Thrown at header.go:478
// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
//
// Return ErrBadTrailer if contain any forbidden trailers.
func (h *header) AddTrailer(trailer string) error {
return h.AddTrailerBytes(s2b(trailer))
}
var (
ErrBadTrailer = errors.New("fasthttp: contain forbidden trailer")
ErrReadingResponseHeaders = errors.New("fasthttp: error when reading response headers")
ErrReadingResponseTrailer = errors.New("fasthttp: error when reading response trailer")
ErrResponseFirstLineMissingSpace = errors.New("fasthttp: cannot find whitespace in the first line of response")
ErrUnexpectedStatusCodeChar = errors.New("fasthttp: unexpected char at the end of status code")
ErrMissingRequestMethod = errors.New("fasthttp: cannot find http request method")
ErrUnsupportedRequestMethod = errors.New("fasthttp: unsupported http request method")
ErrExtraWhitespaceInRequestLine = errors.New("fasthttp: extra whitespace in request line")
ErrEmptyRequestURI = errors.New("fasthttp: requesturi cannot be empty")
ErrDuplicateContentLength = errors.New("fasthttp: duplicate content-length header")
ErrUnsupportedTransferEncoding = errors.New("fasthttp: unsupported transfer-encoding")
ErrNonNumericChars = errors.New("fasthttp: non-numeric chars found")
ErrNeedMore = errors.New("fasthttp: need more data: cannot find trailing lf")
ErrSmallReadBuffer = errors.New("fasthttp: small read buffer. increase readbuffersize")
)
// AddTrailerBytes add Trailer header value for chunked response
// to indicate which headers will be sent after the body.
//
// Use Set to set the trailer header later.
//
// Trailers are only supported with chunked transfer.
// Trailers allow the sender to include additional headers at the end of chunked messages.
//
// The following trailers are forbidden:
// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
// 2. routing (e.g., Host),
// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),View on GitHub (pinned to c96f600972)
Solutions
- Remove the duplicate injection: set Content-Length only once — prefer header.SetContentLength(len(body)) and never also Add("Content-Length", ...).
- Fix intermediate proxies to not add a second Content-Length when one exists.
- Strip the header before forwarding: use h.Del("Content-Length") / h.SetContentLength(-1) for chunked transfer instead.
- Treat incoming duplicate headers from untrusted peers as a security event and reject the connection (fasthttp already aborts the parse).
Example fix
// before
req.Header.SetContentLength(len(body))
req.Header.Add("Content-Length", strconv.Itoa(len(body))) // duplicate
// after
req.Header.SetContentLength(len(body)) Defensive patterns
Strategy: type-guard
Validate before calling
// Before sending, ensure only fasthttp manages framing:
req.Header.Del("Content-Length")
req.Header.SetContentLength(len(body)) // single authoritative setter Type guard
func isDuplicateContentLength(err error) bool {
return err == fasthttp.ErrDuplicateContentLength
} Try / catch
if err := resp.Read(r); err == fasthttp.ErrDuplicateContentLength {
return fmt.Errorf("upstream sent duplicate Content-Length (possible smuggling attempt): %w", err)
} Prevention
- Never call Header.Add("Content-Length", ...) — use SetContentLength only.
- When forwarding headers, strip Content-Length/Transfer-Encoding and let fasthttp recompute framing.
- Check proxy chains for components that append Content-Length to already-framed messages.
- Alert on inbound occurrences — duplicates from untrusted peers are a smuggling probe.
When it happens
Trigger: Response.Read / Request.Read / Client.Do on a message containing two Content-Length headers (e.g. 'Content-Length: 5' twice), commonly produced by misconfigured proxies or by manually appending the header twice via req.Header.SetContentLength followed by h.Add("Content-Length", ...).
Common situations: Front-end and back-end proxies both injecting Content-Length; hand-rolled clients that set the header explicitly while fasthttp also computes it; malicious traffic probing for smuggling vulnerabilities.
Related errors
- fasthttp: extra whitespace in request line
- fasthttp: unsupported transfer-encoding
- fasthttp: non-numeric chars found
- fasthttp: small read buffer. increase readbuffersize
- too many transfer-encoding headers
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/72f092ccfe2c1d96.
Report an issue: GitHub.