guzzle/guzzle · error · RuntimeException

Invalid Content-Length response header: %s

Error message

Invalid Content-Length response header: %s

What it means

Thrown by HeaderProcessor::validateResponseFraming() as a wrapper RuntimeException that re-throws any Content-Length parse failure (error 281 or 282) with a response-specific prefix. It preserves the original cause via the $previous argument. It fires only for responses that are allowed to have a body (excludes HEAD, 1xx, 204, 304, 2xx CONNECT).

Source

Thrown at src/Handler/HeaderProcessor.php:184

     * @throws \RuntimeException when Content-Length is malformed, conflicting,
     *                           or combined with Transfer-Encoding
     */
    public static function validateResponseFraming(
        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

View on GitHub (pinned to d1cbca7697)

Solutions

  1. Read the suffixed detail (the original message) to know whether it was non-integer (281) or conflicting (282).
  2. Capture raw response headers to confirm what the server sent.
  3. Report/fix the origin or intermediary producing the bad header.
  4. Catch RuntimeException around the request when interoperating with the broken endpoint.

Example fix

// before
try {
    $resp = $client->get($url);
} catch (\GuzzleHttp\Exception\RequestException $e) {
    // message is opaque
}

// after - surface the underlying cause
try {
    $resp = $client->get($url);
} catch (\RuntimeException $e) {
    \error_log($e->getMessage().' :: '.($e->getPrevious() ? $e->getPrevious()->getMessage() : ''));
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    $response = $client->get($url);
} catch (\RuntimeException $e) {
    if (str_starts_with($e->getMessage(), 'Invalid Content-Length response header')) {
        $cause = $e->getPrevious() ? $e->getPrevious()->getMessage() : '';
        // log $cause (e.g. 'values conflict' or 'not a non-negative decimal integer')
    }
    throw $e;
}

Prevention

When it happens

Trigger: A response to a body-bearing request carries a malformed or conflicting Content-Length header; validateResponseFraming() catches the underlying RuntimeException from parseContentLength() and rethrows with the 'Invalid Content-Length response header: ' prefix.

Common situations: Same root causes as errors 281/282 but surfaced during response framing validation, typically against a buggy server, gateway, or CDN emitting bad Content-Length.

Related errors


AI-assisted analysis of guzzle/guzzle@d1cbca7697 (2026-08-06). Data as JSON: /api/errors/8ae48d6f1b92eb14. Report an issue: GitHub.