valyala/fasthttp · error · ErrBrokenChunk

cannot read '\r' char at the end of chunk size

Error message

cannot read '\r' char at the end of chunk size: %w

What it means

fasthttp wraps parse failures of a chunked (Transfer-Encoding: chunked) body in ErrBrokenChunk. This variant fires when reading the CR that must terminate the chunk-size line fails at the I/O level — the connection ended or errored before the '\r' byte could be read. The wrapped cause (io.ErrUnexpectedEOF, connection reset, timeout) is inside ErrBrokenChunk.error.

Solutions

  1. Handle ErrBrokenChunk via errors.As and inspect the wrapped cause; treat it as a truncated chunked body from the peer.
  2. Fix the client/proxy that closes the connection before finishing the chunked transfer.
  3. Verify the peer speaks correct chunked encoding (each size line ends with CRLF).
  4. Set/raise read timeouts so slow peers aren't cut off mid-line, and add retry logic for idempotent requests.

Example fix

// before
body, err := ctx.Request.Body()
if err != nil { return err }
// after
body, err := ctx.Request.Body()
var bc fasthttp.ErrBrokenChunk
if errors.As(err, &bc) {
    ctx.Logger().Printf("broken chunked body from %s: %v", ctx.RemoteAddr(), bc.error)
    return // drop malformed request
}
Defensive patterns

Strategy: try-catch

Type guard

func isBrokenChunk(err error) bool {
    var bc fasthttp.ErrBrokenChunk
    return errors.As(err, &bc)
}

Try / catch

var bc fasthttp.ErrBrokenChunk
if errors.As(err, &bc) {
    log.Printf("broken chunked body (read failed): %v", bc.error)
    // connection state is unusable: close it
    ctx.ConnectionClose()
}

Prevention

When it happens

Trigger: Server or client parsing a chunked body when the peer closes or resets the connection mid-chunk-size-line, before sending the trailing CRLF; also triggered by proxies that truncate responses.

Common situations: Client disconnects mid-request on a server; upstream proxy/load balancer cuts the response; flaky network dropping the tail of the body; clients sending malformed chunked framing.

Related errors


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

Appendix: source

Thrown at http.go:2979

				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),
			}
		}
		if c == '\r' {
			if err := r.UnreadByte(); err != nil {
				return -1, ErrBrokenChunk{
					error: fmt.Errorf("cannot unread '\\r' char at the end of chunk size: %w", err),
				}
			}
			break
		}
		// Security: Don't allow newlines in chunk extensions.
		// This can lead to request smuggling issues with some reverse proxies.
		if c == '\n' {
			return -1, ErrBrokenChunk{
				error: errors.New("invalid character '\\n' after chunk size"),
			}
		}
		if inExt {

View on GitHub (pinned to c96f600972)