guzzle/guzzle · error · RuntimeException
A response must not contain both Content-Length and…
Error message
A response must not contain both Content-Length and Transfer-Encoding
What it means
Thrown by HeaderProcessor::validateResponseFraming() when a body-bearing response carries both a Content-Length and a Transfer-Encoding header. RFC 7230 forbids this combination to prevent framing ambiguity and request/response smuggling; the presence of both is a protocol violation.
Solutions
- Capture raw response headers (curl -v) to confirm both headers are present.
- Fix the proxy/gateway to strip one header per RFC 7230 (prefer Transfer-Encoding when chunked).
- If the server is out of your control, catch RuntimeException and decide whether to retry without strict framing.
- Report the violation to the server operator.
Example fix
// before - blind call to a non-conformant server
$resp = $client->get($url);
// after - tolerate the broken endpoint
try {
$resp = $client->get($url);
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'both Content-Length and Transfer-Encoding')) {
// fall back, log, or use a different endpoint
}
throw $e;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
$response = $client->get($url);
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'both Content-Length and Transfer-Encoding')) {
// non-conformant server; fall back or report
}
throw $e;
} Prevention
- Audit reverse proxies/gateways to strip one of the two headers per RFC 7230.
- Use curl -v to detect the dual-header condition on the wire.
- Avoid intermediaries that re-chunk without removing Content-Length.
When it happens
Trigger: A server returns headers like 'Transfer-Encoding: chunked' together with 'Content-Length: 123' on a response that can have a body. validateResponseFraming() detects the overlap after parsing a valid Content-Length and finding a transfer-encoding key.
Common situations: A proxy adds Transfer-Encoding: chunked but does not strip the origin's Content-Length (or vice versa), a misconfigured reverse proxy, or a deliberately non-conformant test server.
Related errors
- values conflict
- Content-Length exceeds the maximum integer size supported…
- Invalid Content-Length response header
- value is not a non-negative decimal integer
- HTTP header line is invalid
AI-assisted analysis of guzzle/guzzle@d1cbca7697 (2026-08-06).
Data as JSON: /api/errors/ea4fdeb2c2fa6021.
Report an issue: GitHub.
Appendix: source
Thrown at src/Handler/HeaderProcessor.php:188
string $method,
int $status,
array $headers
): ?string {
if (!self::responseCanHaveBody($method, $status)) {
return null;
}
$normalizedKeys = Utils::normalizeHeaderKeys($headers);
$contentLength = self::removeHeader('Content-Length', $headers);
try {
$length = self::parseContentLength($contentLength);
} catch (\RuntimeException $e) {
throw new \RuntimeException('Invalid Content-Length response header: '.$e->getMessage(), 0, $e);
}
if ($length !== null && isset($normalizedKeys['transfer-encoding'])) {
throw new \RuntimeException('A response must not contain both Content-Length and Transfer-Encoding');
}
return $length;
}
/**
* Removes every case-insensitive occurrence of a header and returns all
* removed values in their original field order.
*
* @param array<string, string[]> $headers
*
* @return string[] Removed values across all header-name casings
*/
public static function removeHeader(string $name, array &$headers): array
{
$values = [];
foreach ($headers as $key => $headerValues) {View on GitHub (pinned to d1cbca7697)