{"record":{"id":"b45da317c092f512","repo":"cloudflare/cloudflared","slug":"error-setting-content-length-w","errorCode":null,"errorMessage":"Error setting content-length: %w","messagePattern":"Error setting content-length: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"connection/quic_connection.go","lineNumber":373,"sourceCode":"\t\treturn nil, err\n\t}\n\n\treq.Host = host\n\tfor _, metadata := range connectRequest.Metadata {\n\t\tif strings.Contains(metadata.Key, HTTPHeaderKey) {\n\t\t\t// metadata.Key is off the format httpHeaderKey:<HTTPHeader>\n\t\t\thttpHeaderKey := strings.Split(metadata.Key, \":\")\n\t\t\tif len(httpHeaderKey) != 2 {\n\t\t\t\treturn nil, fmt.Errorf(\"header Key: %s malformed\", metadata.Key)\n\t\t\t}\n\t\t\treq.Header.Add(httpHeaderKey[1], metadata.Val)\n\t\t}\n\t}\n\t// Go's http.Client automatically sends chunked request body if this value is not set on the\n\t// *http.Request struct regardless of header:\n\t// https://go.googlesource.com/go/+/go1.8rc2/src/net/http/transfer.go#154.\n\tif err := setContentLength(req); err != nil {\n\t\treturn nil, fmt.Errorf(\"Error setting content-length: %w\", err)\n\t}\n\n\t// Go's client defaults to chunked encoding after a 200ms delay if the following cases are true:\n\t//   * the request body blocks\n\t//   * the content length is not set (or set to -1)\n\t//   * the method doesn't usually have a body (GET, HEAD, DELETE, ...)\n\t//   * there is no transfer-encoding=chunked already set.\n\t// So, if transfer cannot be chunked and content length is 0, we dont set a request body.\n\tif !isWebsocket && !isTransferEncodingChunked(req) && req.ContentLength == 0 {\n\t\treq.Body = http.NoBody\n\t}\n\tstripWebsocketUpgradeHeader(req)\n\n\t// Check for tracing on request\n\ttracedReq := tracing.NewTracedHTTPRequest(req, connIndex, log)\n\treturn tracedReq, err\n}\n","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/connection/quic_connection.go#L355-L391","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Provide a request body with a known length (bytes.Buffer, bytes.Reader, strings.Reader) so ContentLength can be inferred","Explicitly set ContentLength on the upstream request if the client knows the size","Inspect setContentLength's inner error (via %w unwrap) to see why length detection failed","If the body is intentionally unbounded, ensure the origin server accepts chunked encoding and consider bypassing length enforcement"],"exampleFix":"// before\nbody := io.Reader(pipeReader) // unknown length\n// after\nbodyBytes, _ := io.ReadAll(pipeReader)\nreq.Body = io.NopCloser(bytes.NewReader(bodyBytes)) // length now measurable","handlingStrategy":"try-catch","validationCode":"// ensure the body length is known before proxying\nswitch b := body.(type) {\ncase *bytes.Buffer, *bytes.Reader, *strings.Reader:\n\t// length is auto-detected; ok\ndefault:\n\tlog.Println(\"warning: body has unknown length; content-length may fail\")\n}","typeGuard":null,"tryCatchPattern":"req, err := buildHTTPRequest(ctx, connectReq, reader, ...)\nif err != nil {\n\tvar clErr *fmt.wrapError\n\tif errors.As(err, &clErr) && strings.Contains(err.Error(), \"Error setting content-length\") {\n\t\t// fall back to chunked encoding or reject the request with 411 Length Required\n\t}\n\treturn err\n}","preventionTips":["Use bytes.Reader/strings.Reader/bytes.Buffer for request bodies so ContentLength is inferred","Set req.ContentLength explicitly when the size is known","Avoid passing io.Readers without length info for proxied bodies"],"tags":["go","http","content-length","quic"],"backgroundTag":"http-request-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}