valyala/fasthttp · error · ErrBrokenChunk

cannot find crlf at the end of chunk

Error message

cannot find crlf at the end of chunk

What it means

While decoding a chunked transfer-encoding body, fasthttp expects each chunk's data to be terminated by CRLF. If the bytes at the expected end-of-chunk position are not \r\n, it wraps this error in ErrBrokenChunk, signaling malformed or truncated chunked data.

Source

Thrown at http.go:2961

	strCRLFLen := len(strCRLF)
	for {
		chunkSize, err := parseChunkSize(r)
		if err != nil {
			return dst, err
		}
		if chunkSize == 0 {
			return dst, err
		}
		if maxBodySize > 0 && len(dst)+chunkSize > maxBodySize {
			return dst, ErrBodyTooLarge
		}
		dst, err = appendBodyFixedSize(r, dst, chunkSize+strCRLFLen)
		if err != nil {
			return dst, err
		}
		if !bytes.Equal(dst[len(dst)-strCRLFLen:], strCRLF) {
			return dst, ErrBrokenChunk{
				error: errors.New("cannot find crlf at the end of chunk"),
			}
		}
		dst = dst[:len(dst)-strCRLFLen]
	}
}

func parseChunkSize(r *bufio.Reader) (int, error) {
	n, err := readHexInt(r)
	if err != nil {
		return -1, err
	}
	inExt := false
	afterSizeOWS := false
	for {
		c, err := r.ReadByte()
		if err != nil {
			return -1, ErrBrokenChunk{
				error: fmt.Errorf("cannot read '\\r' char at the end of chunk size: %w", err),

View on GitHub (pinned to c96f600972)

Solutions

  1. Verify the sender produces standards-compliant chunked encoding (each chunk followed by CRLF).
  2. Check intermediaries (proxies, gateways) for re-chunking bugs; bypass or upgrade them.
  3. Inspect the peer's output and network for truncation/corruption; retry the request on a fresh connection.

Example fix

// before (malformed peer output)
5\r\nhelloX\r\n // missing trailing CRLF -> ErrBrokenChunk
// after (valid chunked framing)
5\r\nhello\r\n0\r\n\r\n
Defensive patterns

Strategy: retry

Try / catch

var broken fasthttp.ErrBrokenChunk
err := client.Do(req, resp)
if errors.As(err, &broken) && strings.Contains(broken.Error(), "cannot find crlf") {
    // discard response, retry on a fresh connection
    req.ConnectionClose = true
    err = client.Do(req, resp)
}

Prevention

When it happens

Trigger: A peer sends chunked data where chunk-size and the CRLF after the chunk payload do not match; the connection delivers a truncated chunk; a non-HTTP client speaks on a chunked endpoint; chunkSize computed from a corrupted size header misaligns the stream.

Common situations: Buggy proxies/servers emitting malformed chunked responses; man-in-the-middle or connection corruption; request-smuggling probes (fasthttp deliberately rejects this); reading a stream that ends mid-chunk.

Related errors


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