valyala/fasthttp · error · ErrBrokenChunk
cannot read '\r' char at the end of chunk size: %w
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.
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)
Solutions
- Handle ErrBrokenChunk via errors.As and inspect the wrapped cause; treat it as a truncated chunked body from the peer.
- Fix the client/proxy that closes the connection before finishing the chunked transfer.
- Verify the peer speaks correct chunked encoding (each size line ends with CRLF).
- 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
- Handle ErrBrokenChunk with errors.As and inspect the wrapped I/O cause.
- Set sane read timeouts so slow peers aren't cut mid-line.
- Monitor for these errors per client IP to detect broken clients/proxies.
- Retry idempotent requests on connection-level failures.
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
- invalid character %q after chunk size
- cannot read %q char at the end of chunk size: %w
- unexpected char %q at the end of chunk size: expected %q
- empty hex number
- cannot unread '\r' char at the end of chunk size: %w
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/36fb97bca186bb89.
Report an issue: GitHub.