{"record":{"id":"a153eabfb1e0b38e","repo":"valyala/fasthttp","slug":"copied-d-bytes-from-body-stream-instead-of-d-byt","errorCode":null,"errorMessage":"copied %d bytes from body stream instead of %d bytes","messagePattern":"copied (.+?) bytes from body stream instead of (.+?) bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"http.go","lineNumber":2655,"sourceCode":"\t\tswitch r := r.(type) {\n\t\tcase *os.File:\n\t\t\tearlyFlush = true\n\t\tcase *io.LimitedReader:\n\t\t\t_, earlyFlush = r.R.(*os.File)\n\t\t}\n\t\tif earlyFlush {\n\t\t\t// w buffer must be empty for triggering\n\t\t\t// sendfile path in bufio.Writer.ReadFrom.\n\t\t\tif err := w.Flush(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\tn, err := copyBodyStream(w, r)\n\n\tif n != size && err == nil {\n\t\terr = fmt.Errorf(\"copied %d bytes from body stream instead of %d bytes\", n, size)\n\t}\n\treturn err\n}\n\nfunc copyBodyStream(w io.Writer, r io.Reader) (int64, error) {\n\tif bwt, ok := r.(BodyWriterTo); ok {\n\t\tif bwt.SupportsBodyWriteTo() {\n\t\t\treturn bwt.WriteTo(w)\n\t\t}\n\n\t\tvbuf := copyBufPool.Get()\n\t\tbuf := vbuf.([]byte) //nolint:forcetypeassert\n\t\tn, err := copyBuffer(w, r, buf)\n\t\tcopyBufPool.Put(vbuf)\n\t\treturn n, err\n\t}\n\n\treturn copyZeroAlloc(w, r)","sourceCodeStart":2637,"sourceCodeEnd":2673,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/http.go#L2637-L2673","documentation":"After copying a response body stream to the wire, fasthttp compares the number of bytes copied with the declared Content-Length/size; if they differ without another error, it reports this mismatch. The transfer was malformed — the body did not contain the promised number of bytes — so the response/request is invalid (e.g. chunked framing or connection will be closed).","triggerScenarios":"resp.SetBodyStream(r, N) where r yields fewer (or more) than N bytes; writeBodyStream's copyBodyStream returns n != size with err == nil (stream hit EOF early or produced extra data).","commonSituations":"Computing the byte count of a generated body incorrectly (uncompressed size vs gzip size); reader short-reads returning io.EOF before N bytes; using a compressed stream length as the size hint for uncompressed data.","solutions":["Make the declared size exactly match the bytes the stream will produce (or pass -1 to use chunked transfer).","Compute sizes on already-final data (e.g. len(compressedBytes)) not estimates.","Fix the reader to return io.EOF only after emitting all promised bytes.","Inspect the wrapped copy error first — often a real read error accompanies the mismatch."],"exampleFix":"// before\nresp.SetBodyStream(gzippedReader, len(rawData)) // wrong size\n// after\nvar buf bytes.Buffer\nzw := gzip.NewWriter(&buf)\nzw.Write(rawData); zw.Close()\nresp.SetBodyStream(bytes.NewReader(buf.Bytes()), buf.Len())","handlingStrategy":"validation","validationCode":"var buf bytes.Buffer\nn, err := io.Copy(&buf, stream)\nif err != nil { return err }\nif int64(n) != declaredSize { return fmt.Errorf(\"stream yields %d bytes, declared %d\", n, declaredSize) }","typeGuard":"func exactReader(r io.Reader, size int64) io.Reader {\n    return io.LimitReader(r, size) // pair with verifying total bytes produced\n}","tryCatchPattern":"if err := client.Do(req, resp); err != nil {\n    if strings.Contains(err.Error(), \"instead of\") &&\n        strings.Contains(err.Error(), \"body stream\") {\n        return fmt.Errorf(\"declared size mismatch; use -1 for chunked: %w\", err)\n    }\n    return err\n}","preventionTips":["Pass -1 to SetBodyStream to use chunked encoding when size is unknown","Buffer and measure generated bodies before declaring a size","Never use uncompressed size as the hint for compressed streams","Fix readers that short-read and return io.EOF early"],"tags":["content-length","body-stream","streaming"],"backgroundTag":"content-length-mismatch","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}