{"record":{"id":"b31fae59ddaa7d70","repo":"crowdsecurity/crowdsec","slug":"failed-to-read-body-w","errorCode":null,"errorMessage":"failed to read body: %w","messagePattern":"failed to read body: %w","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/acquisition/modules/http/run.go","lineNumber":58,"sourceCode":"\t\tfor key, value := range hc.Headers {\n\t\t\tif r.Header.Get(key) != value {\n\t\t\t\treturn errors.New(\"invalid headers\")\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc rejectBody(w http.ResponseWriter, err error) error {\n\tif maxBytesErr, ok := errors.AsType[*http.MaxBytesError](err); ok {\n\t\tw.WriteHeader(http.StatusRequestEntityTooLarge)\n\t\treturn fmt.Errorf(\"body size exceeds max body size: %d\", maxBytesErr.Limit)\n\t}\n\n\tw.WriteHeader(http.StatusBadRequest)\n\n\treturn fmt.Errorf(\"failed to read body: %w\", err)\n}\n\nfunc (s *Source) processRequest(w http.ResponseWriter, r *http.Request, hc *Configuration, out chan pipeline.Event) error {\n\t// Shortcut for clients announcing an oversized body, so we don't read it at all.\n\tif hc.MaxBodySize != nil && r.ContentLength > *hc.MaxBodySize {\n\t\tw.WriteHeader(http.StatusRequestEntityTooLarge)\n\t\treturn fmt.Errorf(\"body size exceeds max body size: %d > %d\", r.ContentLength, *hc.MaxBodySize)\n\t}\n\n\tsrcHost, _, err := net.SplitHostPort(r.RemoteAddr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Content-Length can be absent (chunked, HTTP/2) or a lie, so bound what we actually read.\n\t// This also caps gzip streams that consume input without producing output.\n\tif hc.MaxBodySize != nil {\n\t\tr.Body = http.MaxBytesReader(w, r.Body, *hc.MaxBodySize)","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/http/run.go#L40-L76","documentation":"rejectBody wraps any body-read error that is not an *http.MaxBytesError, after sending HTTP 400 to the client. It means the request body could not be read at all (connection issue, malformed chunked encoding, client abort).","triggerScenarios":"processRequest reads r.Body via http.MaxBytesReader and io.ReadAll fails with a non-limit error: client disconnects mid-body, invalid chunked transfer encoding, or I/O error on the connection.","commonSituations":"Clients timing out and dropping the connection mid-upload; proxies (nginx/LB) closing upstream connections prematurely; broken/malformed chunked encoding from a custom client.","solutions":["Check client/proxy logs for early disconnects and timeouts; increase proxy read timeouts (e.g. nginx proxy_read_timeout).","Fix the sending client's transfer encoding (prefer Content-Length or correct chunked framing).","Retry the request from the client; the 400 response indicates the server discarded it.","Inspect server-side network issues (MTU, TLS handshake truncation) if it reproduces on large bodies."],"exampleFix":"# nginx proxy before/after\n# before\nproxy_read_timeout 30s;\n# after\nproxy_read_timeout 300s;","handlingStrategy":"retry","validationCode":null,"typeGuard":"var maxBytesErr *http.MaxBytesError; if errors.As(err, &maxBytesErr) { /* treat as 413, not retryable this way */ }","tryCatchPattern":"if strings.Contains(err.Error(), \"failed to read body\") && !is413 { time.Sleep(backoff); retry(request) }","preventionTips":["Set client and proxy timeouts above server read time.","Use Content-Length instead of broken chunked framing.","Check LB/proxy idle timeout settings."],"tags":["http","body","io"],"backgroundTag":"invalid-json-response","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}