guzzle/guzzle · error · GuzzleHttp\Exception\InvalidArgumentException

The "transport_sharing" option requires persistent transport

Error message

The "transport_sharing" option requires persistent transport sharing, which is only available through cURL share handles.

What it means

Raised in assertTransportSharingSupported() at src/Handler/StreamHandler.php:1370 when the handler was constructed with transport_sharing = TransportSharing::PERSISTENT_REQUIRE. That mode demands cross-process / cross-handle state sharing via cURL share handles, which the stream handler cannot provide, so the request is rejected on first use.

Source

Thrown at src/Handler/StreamHandler.php:1370

                'cafile' => 'the "verify" request option',
                'capath' => 'the "verify" request option',
                'crypto_method' => 'the "crypto_method" request option',
                'local_cert' => 'the "cert" request option',
                'local_pk' => 'the "ssl_key" request option',
                'max_proto_version' => 'the "crypto_method_max" request option',
                'min_proto_version' => 'the "crypto_method" request option',
                'passphrase' => 'the "cert" or "ssl_key" request option',
                'peer_name' => 'the request URI',
                'verify_peer' => 'the "verify" request option',
                'verify_peer_name' => 'the "verify" request option',
            ],
        ];
    }

    private function assertTransportSharingSupported(): void
    {
        if ($this->transportSharingMode === TransportSharing::PERSISTENT_REQUIRE) {
            throw new InvalidArgumentException('The "transport_sharing" option requires persistent transport sharing, which is only available through cURL share handles.');
        }

        if ($this->transportSharingMode === TransportSharing::HANDLER_REQUIRE) {
            throw new InvalidArgumentException('The "transport_sharing" option requires transport sharing, but the stream handler does not support it.');
        }
    }

    /**
     * @param mixed $value as passed via Request transfer options.
     *
     * @return array{0: string, 1: string|null}
     */
    private static function normalizeTlsFileOption(
        string $option,
        #[\SensitiveParameter]
        $value
    ): array {
        $passphrase = null;

View on GitHub (pinned to 9b200fc580)

Solutions

  1. Downgrade to TransportSharing::PERSISTENT_PREFER (silently no-ops on StreamHandler) or TransportSharing::NONE.
  2. Use CurlHandler or CurlMultiHandler when you require persistent sharing.
  3. Branch the transport_sharing option by handler type.

Example fix

// before
$handler = new StreamHandler(['transport_sharing' => TransportSharing::PERSISTENT_REQUIRE]);

// after
$handler = new StreamHandler(['transport_sharing' => TransportSharing::PERSISTENT_PREFER]);
// or use new CurlMultiHandler(['transport_sharing' => TransportSharing::PERSISTENT_REQUIRE])
Defensive patterns

Strategy: validation

Validate before calling

if ($handler instanceof \GuzzleHttp\Handler\StreamHandler
    && $transportSharing === \GuzzleHttp\TransportSharing::PERSISTENT_REQUIRE
) {
    throw new InvalidArgumentException(
        'StreamHandler cannot provide persistent transport sharing; use PERSISTENT_PREFER or a cURL handler.'
    );
}

Prevention

When it happens

Trigger: new StreamHandler(['transport_sharing' => TransportSharing::PERSISTENT_REQUIRE]) followed by any request through that handler.

Common situations: Sharing a config array across CurlHandler and StreamHandler; defaulting the whole application to PERSISTENT_REQUIRE; assuming all handlers support persistent sharing.

Related errors


AI-assisted analysis of guzzle/guzzle@9b200fc580 (2026-08-04). Data as JSON: /data/errors/08f1af5a1db547ed.json. Report an issue: GitHub.