{"record":{"id":"36fb97bca186bb89","repo":"valyala/fasthttp","slug":"cannot-read-r-char-at-the-end-of-chunk-size-w","errorCode":null,"errorMessage":"cannot read '\\r' char at the end of chunk size: %w","messagePattern":"cannot read '\\\\r' char at the end of chunk size: %w","errorType":"exception","errorClass":"ErrBrokenChunk","httpStatus":null,"severity":"error","filePath":"http.go","lineNumber":2979,"sourceCode":"\t\t\t\terror: errors.New(\"cannot find crlf at the end of chunk\"),\n\t\t\t}\n\t\t}\n\t\tdst = dst[:len(dst)-strCRLFLen]\n\t}\n}\n\nfunc parseChunkSize(r *bufio.Reader) (int, error) {\n\tn, err := readHexInt(r)\n\tif err != nil {\n\t\treturn -1, err\n\t}\n\tinExt := false\n\tafterSizeOWS := false\n\tfor {\n\t\tc, err := r.ReadByte()\n\t\tif err != nil {\n\t\t\treturn -1, ErrBrokenChunk{\n\t\t\t\terror: fmt.Errorf(\"cannot read '\\\\r' char at the end of chunk size: %w\", err),\n\t\t\t}\n\t\t}\n\t\tif c == '\\r' {\n\t\t\tif err := r.UnreadByte(); err != nil {\n\t\t\t\treturn -1, ErrBrokenChunk{\n\t\t\t\t\terror: fmt.Errorf(\"cannot unread '\\\\r' char at the end of chunk size: %w\", err),\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t\t// Security: Don't allow newlines in chunk extensions.\n\t\t// This can lead to request smuggling issues with some reverse proxies.\n\t\tif c == '\\n' {\n\t\t\treturn -1, ErrBrokenChunk{\n\t\t\t\terror: errors.New(\"invalid character '\\\\n' after chunk size\"),\n\t\t\t}\n\t\t}\n\t\tif inExt {","sourceCodeStart":2961,"sourceCodeEnd":2997,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/http.go#L2961-L2997","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nbody, err := ctx.Request.Body()\nif err != nil { return err }\n// after\nbody, err := ctx.Request.Body()\nvar bc fasthttp.ErrBrokenChunk\nif errors.As(err, &bc) {\n    ctx.Logger().Printf(\"broken chunked body from %s: %v\", ctx.RemoteAddr(), bc.error)\n    return // drop malformed request\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isBrokenChunk(err error) bool {\n    var bc fasthttp.ErrBrokenChunk\n    return errors.As(err, &bc)\n}","tryCatchPattern":"var bc fasthttp.ErrBrokenChunk\nif errors.As(err, &bc) {\n    log.Printf(\"broken chunked body (read failed): %v\", bc.error)\n    // connection state is unusable: close it\n    ctx.ConnectionClose()\n}","preventionTips":["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."],"tags":["fasthttp","chunked-encoding","http-protocol","truncated-body"],"backgroundTag":"broken-chunked-body","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}