crowdsecurity/crowdsec · error
failed to read body: %w
Error message
failed to read body: %w
What it means
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).
Source
Thrown at pkg/acquisition/modules/http/run.go:58
for key, value := range hc.Headers {
if r.Header.Get(key) != value {
return errors.New("invalid headers")
}
}
}
return nil
}
func rejectBody(w http.ResponseWriter, err error) error {
if maxBytesErr, ok := errors.AsType[*http.MaxBytesError](err); ok {
w.WriteHeader(http.StatusRequestEntityTooLarge)
return fmt.Errorf("body size exceeds max body size: %d", maxBytesErr.Limit)
}
w.WriteHeader(http.StatusBadRequest)
return fmt.Errorf("failed to read body: %w", err)
}
func (s *Source) processRequest(w http.ResponseWriter, r *http.Request, hc *Configuration, out chan pipeline.Event) error {
// Shortcut for clients announcing an oversized body, so we don't read it at all.
if hc.MaxBodySize != nil && r.ContentLength > *hc.MaxBodySize {
w.WriteHeader(http.StatusRequestEntityTooLarge)
return fmt.Errorf("body size exceeds max body size: %d > %d", r.ContentLength, *hc.MaxBodySize)
}
srcHost, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return err
}
// Content-Length can be absent (chunked, HTTP/2) or a lie, so bound what we actually read.
// This also caps gzip streams that consume input without producing output.
if hc.MaxBodySize != nil {
r.Body = http.MaxBytesReader(w, r.Body, *hc.MaxBodySize)View on GitHub (pinned to 909b515798)
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.
Example fix
# nginx proxy before/after # before proxy_read_timeout 30s; # after proxy_read_timeout 300s;
Defensive patterns
Strategy: retry
Type guard
var maxBytesErr *http.MaxBytesError; if errors.As(err, &maxBytesErr) { /* treat as 413, not retryable this way */ } Try / catch
if strings.Contains(err.Error(), "failed to read body") && !is413 { time.Sleep(backoff); retry(request) } Prevention
- Set client and proxy timeouts above server read time.
- Use Content-Length instead of broken chunked framing.
- Check LB/proxy idle timeout settings.
When it happens
Trigger: 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.
Common situations: Clients timing out and dropping the connection mid-upload; proxies (nginx/LB) closing upstream connections prematurely; broken/malformed chunked encoding from a custom client.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
- unable to read body: %w
- path must start with /
- chunk_size must be positive
- invalid HTTP status code
- missing basic auth
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/b31fae59ddaa7d70.
Report an issue: GitHub.