guzzle/guzzle · error · GuzzleHttp\Exception\RequestException
The stream handler cannot guarantee a multiplexed protocol;
Error message
The stream handler cannot guarantee a multiplexed protocol; required multiplexing needs a cURL handler.
What it means
Thrown by StreamHandler::__invoke when the 'multiplex' option is Multiplexing::REQUIRE_EAGER or REQUIRE_WAIT. The stream handler speaks only HTTP/1.x (one request per connection) and can never provide a multiplexed protocol, so a hard requirement for multiplexing cannot be satisfied and is rejected before any I/O rather than silently degrading.
Source
Thrown at src/Handler/StreamHandler.php:174
// Sleep if there is a delay specified.
if (isset($options['delay'])) {
\usleep((int) ($options['delay'] * 1000));
}
$multiplex = $options['multiplex'] ?? null;
// Multiplexing::NONE is trivially satisfied: the stream handler sends
// one HTTP/1.x request per connection and never multiplexes.
if (null !== $multiplex && !\in_array($multiplex, [Multiplexing::NONE, Multiplexing::EAGER, Multiplexing::WAIT, Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) {
throw new InvalidArgumentException(\sprintf(
'The "multiplex" option must be null or a GuzzleHttp\\Multiplexing::* constant; received %s.',
\get_debug_type($multiplex)
));
}
if (\in_array($multiplex, [Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) {
throw new RequestException('The stream handler cannot guarantee a multiplexed protocol; required multiplexing needs a cURL handler.', $request);
}
$protocolVersion = $request->getProtocolVersion();
if ('' === $protocolVersion) {
throw new RequestException('HTTP protocol version must not be empty.', $request);
}
if (1 !== \preg_match('/^\d+(?:\.\d+)?$/D', $protocolVersion)) {
throw new RequestException('HTTP protocol version must be a valid HTTP version number.', $request);
}
if ('1.0' !== $protocolVersion && '1.1' !== $protocolVersion) {
throw new RequestException(sprintf('HTTP/%s is not supported by the stream handler.', $protocolVersion), $request);
}
if (isset($options['on_stats']) && !\is_callable($options['on_stats'])) {
throw new InvalidArgumentException('on_stats must be callable');View on GitHub (pinned to 9b200fc580)
Solutions
- Use a cURL-based handler (CurlMultiHandler) which supports HTTP/2 multiplexing for REQUIRE_EAGER/REQUIRE_WAIT.
- Downgrade the requirement to Multiplexing::EAGER or WAIT if multiplexing is preferred but not mandatory.
- Ensure the ext-curl extension is installed so the default handler is cURL, not the stream handler.
Example fix
// before
$handler = new StreamHandler();
$client->request('GET', $url, ['multiplex' => Multiplexing::REQUIRE_EAGER]);
// after
$handler = HandlerStack::create(); // uses CurlMultiHandler when ext-curl is present
$client->request('GET', $url, ['multiplex' => Multiplexing::REQUIRE_EAGER]); Defensive patterns
Strategy: fallback
Validate before calling
// Choose the handler based on whether multiplexing is required.
$needMultiplex = in_array($reqOptions['multiplex'] ?? null, [Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true);
$handler = $needMultiplex && function_exists('curl_init')
? new CurlMultiHandler()
: new StreamHandler(); Prevention
- Ensure ext-curl is installed so the default handler supports HTTP/2 multiplexing.
- Do not REQUIRE multiplexing unless your handler stack is cURL-based.
- Use EAGER/WAIT (preference) instead of REQUIRE_* unless multiplexing is mandatory.
When it happens
Trigger: Configuring the client/handler with a StreamHandler (or falling back to it) while a request sets 'multiplex' => Multiplexing::REQUIRE_EAGER or REQUIRE_WAIT to demand an HTTP/2 connection.
Common situations: Defaulting to StreamHandler on systems without the cURL extension; building a handler stack that prefers cURL but falls back to StreamHandler while requests demand multiplexing; misreading REQUIRE_* semantics.
Related errors
- HTTP/%s is not supported by the stream handler.
- Required multiplexing needs libcurl 8.14.0 or newer built wi
- Required multiplexing cannot be guaranteed for cleartext req
- The "multiplex" request option can only be Multiplexing::NON
- The "multiplex" option must be null or a GuzzleHttp\Multiple
AI-assisted analysis of guzzle/guzzle@9b200fc580 (2026-08-04).
Data as JSON: /data/errors/2914202916a58396.json.
Report an issue: GitHub.