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

  1. Check client/proxy logs for early disconnects and timeouts; increase proxy read timeouts (e.g. nginx proxy_read_timeout).
  2. Fix the sending client's transfer encoding (prefer Content-Length or correct chunked framing).
  3. Retry the request from the client; the 400 response indicates the server discarded it.
  4. 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

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


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/b31fae59ddaa7d70. Report an issue: GitHub.