guzzle/guzzle · error · GuzzleHttp\Exception\InvalidArgumentException
The "multiplex" request option cannot be Multiplexing::NONE
Error message
The "multiplex" request option cannot be Multiplexing::NONE on a CurlMultiHandler that permits multiplexing and requires persistent transport sharing; set the "multiplex" client or CurlMultiHandler constructor option to Multiplexing::NONE, or use TransportSharing::PERSISTENT_PREFER.
What it means
Thrown by CurlMultiHandler::applyMultiplexNone() when the per-request multiplex option is NONE on a multiplexing handler, the request is HTTP/1.x, but the handler's transport sharing mode is TransportSharing::PERSISTENT_REQUIRE. Enforcing NONE on older libcurl (without reliable reuse matching) forces a fresh connection, which persistent-require sharing forbids because it disables reuse. The two requirements are incompatible, so it fails closed.
Source
Thrown at src/Handler/CurlMultiHandler.php:432
return;
}
if (!$this->ownsFactory) {
throw new InvalidArgumentException('The "multiplex" request option can only be Multiplexing::NONE on a CurlMultiHandler with a custom "handle_factory" when the handler\'s own "multiplex" option is Multiplexing::NONE, because the guarantee is enforced against the native easy handle the factory controls.');
}
$version = $easy->request->getProtocolVersion();
if ('1.0' !== $version && '1.1' !== $version) {
throw new InvalidArgumentException('The "multiplex" request option can only be Multiplexing::NONE for an HTTP/1.x request on a CurlMultiHandler that permits multiplexing; set the "multiplex" client or CurlMultiHandler constructor option to Multiplexing::NONE to disable multiplexing for every transfer, or send the request with its "version" option set to "1.1".');
}
if (null !== $this->shareHandleState && TransportSharing::PERSISTENT_REQUIRE === $this->shareHandleState->mode) {
// The matcher-window hardening below may force a fresh
// connection, which required persistent sharing forbids because
// it disables connection reuse (CurlFactory applies the same
// rule to the raw option); rejected on every runtime so
// acceptance stays version-independent.
throw new InvalidArgumentException('The "multiplex" request option cannot be Multiplexing::NONE on a CurlMultiHandler that permits multiplexing and requires persistent transport sharing; set the "multiplex" client or CurlMultiHandler constructor option to Multiplexing::NONE, or use TransportSharing::PERSISTENT_PREFER.');
}
if (\defined('CURLOPT_HTTPAUTH')
&& isset($options['curl'])
&& \is_array($options['curl'])
&& \array_key_exists((int) \constant('CURLOPT_HTTPAUTH'), $options['curl'])
) {
// Key presence alone conflicts: challenge-response retries are
// libcurl-internal follows, which disarm CURLOPT_FRESH_CONNECT
// (reuse_fresh && !this_is_a_follow), so the hardening below
// cannot cover them.
throw new InvalidArgumentException('The "multiplex" request option cannot be Multiplexing::NONE combined with the raw CURLOPT_HTTPAUTH cURL option on a CurlMultiHandler that permits multiplexing; remove the raw option, or set the "multiplex" client or CurlMultiHandler constructor option to Multiplexing::NONE.');
}
if (Psr7\Utils::caselessContains($easy->request->getHeaderLine('Expect'), '100-continue')) {
// libcurl arms its Expect handling by a caseless substring scan
// of the header value (Curl_compareheader), so any value
// containing 100-continue can make a 417 response retry as anView on GitHub (pinned to 9b200fc580)
Solutions
- Switch sharing to TransportSharing::PERSISTENT_PREFER, which does not forbid fresh connections.
- Disable multiplexing globally (handler/client multiplex => NONE) so NONE does not need hardening.
- Drop the per-request NONE for that transfer.
Example fix
// before new CurlMultiHandler(['transport_sharing' => TransportSharing::PERSISTENT_REQUIRE]); $client->get($url, ['multiplex' => Multiplexing::NONE]); // after new CurlMultiHandler(['transport_sharing' => TransportSharing::PERSISTENT_PREFER]); $client->get($url, ['multiplex' => Multiplexing::NONE]);
Defensive patterns
Strategy: validation
Validate before calling
use GuzzleHttp\TransportSharing;
if (($handlerOptions['transport_sharing'] ?? null) === TransportSharing::PERSISTENT_REQUIRE
&& ($requestOptions['multiplex'] ?? null) === GuzzleHttp\Multiplexing::NONE
) {
throw new InvalidArgumentException('PERSISTENT_REQUIRE sharing forbids the fresh-connection hardening that NONE may need');
} Prevention
- PERSISTENT_REQUIRE forbids fresh connections; use PERSISTENT_PREFER if you also need NONE.
- Disable multiplexing globally to avoid per-request hardening.
- Do not request per-transfer isolation under required persistent pooling.
When it happens
Trigger: Handler built with transport_sharing => TransportSharing::PERSISTENT_REQUIRE (default multiplexing on); request with multiplex => NONE on libcurl below 7.77.0 (or 8.11.0-8.12.1) where the hardening would force a fresh connection.
Common situations: Requiring persistent connection pooling for throughput while trying to isolate a single sensitive transfer; the requirement and the isolation contradict.
Related errors
- The "transport_sharing" client option can only require shari
- The cURL share handle state mode does not match the configur
- A cURL share handle cannot be provided when transport sharin
- A cURL share handle is required when transport sharing is en
- Persistent cURL sharing is required, but this request requir
AI-assisted analysis of guzzle/guzzle@9b200fc580 (2026-08-04).
Data as JSON: /data/errors/38e1812b62b89daa.json.
Report an issue: GitHub.