cloudflare/cloudflared · error

Error setting content-length: %w

Error message

Error setting content-length: %w

What it means

After building the origin request, buildHTTPRequest calls setContentLength to ensure the request is not silently sent with chunked transfer encoding. If setContentLength fails (e.g. the request body does not support Len()/known length), the error is wrapped as "Error setting content-length". Without this, Go's http.Client would buffer or chunk bodies unexpectedly, breaking some origin servers.

Source

Thrown at connection/quic_connection.go:373

		return nil, err
	}

	req.Host = host
	for _, metadata := range connectRequest.Metadata {
		if strings.Contains(metadata.Key, HTTPHeaderKey) {
			// metadata.Key is off the format httpHeaderKey:<HTTPHeader>
			httpHeaderKey := strings.Split(metadata.Key, ":")
			if len(httpHeaderKey) != 2 {
				return nil, fmt.Errorf("header Key: %s malformed", metadata.Key)
			}
			req.Header.Add(httpHeaderKey[1], metadata.Val)
		}
	}
	// Go's http.Client automatically sends chunked request body if this value is not set on the
	// *http.Request struct regardless of header:
	// https://go.googlesource.com/go/+/go1.8rc2/src/net/http/transfer.go#154.
	if err := setContentLength(req); err != nil {
		return nil, fmt.Errorf("Error setting content-length: %w", err)
	}

	// Go's client defaults to chunked encoding after a 200ms delay if the following cases are true:
	//   * the request body blocks
	//   * the content length is not set (or set to -1)
	//   * the method doesn't usually have a body (GET, HEAD, DELETE, ...)
	//   * there is no transfer-encoding=chunked already set.
	// So, if transfer cannot be chunked and content length is 0, we dont set a request body.
	if !isWebsocket && !isTransferEncodingChunked(req) && req.ContentLength == 0 {
		req.Body = http.NoBody
	}
	stripWebsocketUpgradeHeader(req)

	// Check for tracing on request
	tracedReq := tracing.NewTracedHTTPRequest(req, connIndex, log)
	return tracedReq, err
}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Provide a request body with a known length (bytes.Buffer, bytes.Reader, strings.Reader) so ContentLength can be inferred
  2. Explicitly set ContentLength on the upstream request if the client knows the size
  3. Inspect setContentLength's inner error (via %w unwrap) to see why length detection failed
  4. If the body is intentionally unbounded, ensure the origin server accepts chunked encoding and consider bypassing length enforcement

Example fix

// before
body := io.Reader(pipeReader) // unknown length
// after
bodyBytes, _ := io.ReadAll(pipeReader)
req.Body = io.NopCloser(bytes.NewReader(bodyBytes)) // length now measurable
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the body length is known before proxying
switch b := body.(type) {
case *bytes.Buffer, *bytes.Reader, *strings.Reader:
	// length is auto-detected; ok
default:
	log.Println("warning: body has unknown length; content-length may fail")
}

Try / catch

req, err := buildHTTPRequest(ctx, connectReq, reader, ...)
if err != nil {
	var clErr *fmt.wrapError
	if errors.As(err, &clErr) && strings.Contains(err.Error(), "Error setting content-length") {
		// fall back to chunked encoding or reject the request with 411 Length Required
	}
	return err
}

Prevention

When it happens

Trigger: The proxied request's body cannot provide a deterministic content length — e.g. a body whose ContentLength is -1 and whose reader cannot be measured, so setContentLength cannot determine or set req.ContentLength.

Common situations: Streaming request bodies of unknown size from the origin client; bodies wrapped in readers that don't implement length introspection; very large uploads that edge delivers as unbounded streams.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/b45da317c092f512. Report an issue: GitHub.