{"id":"ede3550598ea5b44","repo":"guzzle/guzzle","slug":"connection-cap-options-require-a-cap-capable-curl","errorCode":null,"errorMessage":"Connection cap options require a cap-capable cURL multi handler or the allow_url_fopen ini setting for stream fallback.","messagePattern":"Connection cap options require a cap-capable cURL multi handler or the allow_url_fopen ini setting for stream fallback\\.","errorType":"exception","errorClass":"\\RuntimeException","httpStatus":null,"severity":"critical","filePath":"src/Utils.php","lineNumber":104,"sourceCode":"            $sharingMode = TransportSharing::HANDLER_PREFER;\n        }\n\n        $handler = self::createCurlHandler($sharingMode, $handlerOptions);\n\n        if ($sharingRequired && $handler === null) {\n            throw new \\RuntimeException('Required transport sharing requires the PHP cURL extension, curl_exec() or curl_multi_exec(), and a supported libcurl version with SSL support.');\n        }\n\n        if (\\ini_get('allow_url_fopen')) {\n            return self::addStreamHandler($handler, $sharingMode, self::connectionCapOptions($handlerOptions));\n        }\n\n        if ($handler !== null) {\n            return $handler;\n        }\n\n        if ($connectionCapsRequired) {\n            throw new \\RuntimeException('Connection cap options require a cap-capable cURL multi handler or the allow_url_fopen ini setting for stream fallback.');\n        }\n\n        throw new \\RuntimeException('GuzzleHttp requires a supported cURL version with SSL support, the allow_url_fopen ini setting, or a custom HTTP handler.');\n    }\n\n    private static function isTransportSharingRequired(string $sharingMode): bool\n    {\n        return \\in_array($sharingMode, [TransportSharing::HANDLER_REQUIRE, TransportSharing::PERSISTENT_REQUIRE], true);\n    }\n\n    /**\n     * @param array{max_host_connections?: mixed, max_total_connections?: mixed} $handlerOptions\n     */\n    private static function hasConnectionCapOptions(array $handlerOptions): bool\n    {\n        return self::connectionCapOptions($handlerOptions) !== [];\n    }\n","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/guzzle/guzzle/blob/9b200fc5805036b331d6031199880dadecae0275/src/Utils.php#L86-L122","documentation":"chooseHandler() throws RuntimeException when the user requested connection caps (max_host_connections and/or max_total_connections) but no cap-capable cURL multi handler exists (curl_multi_exec missing) AND allow_url_fopen is disabled. Caps need CurlMultiHandler; the stream fallback path only exists when allow_url_fopen is on.","triggerScenarios":"Setting max_host_connections / max_total_connections in handler options on a runtime without curl_multi_exec and with allow_url_fopen=0 in php.ini.","commonSituations":"Locking down allow_url_fopen for security while expecting connection caps without ensuring ext-curl (with multi) is present; minimal images that strip either curl or fopen.","solutions":["Ensure ext-curl with multi support is installed (curl_multi_exec must exist): php -r 'var_dump(function_exists(\"curl_multi_exec\"));'.","Enable allow_url_fopen=1 in php.ini as a stream fallback (note security trade-offs).","Drop the connection-cap options if neither is feasible.","Note: caps cannot be combined with TransportSharing::PERSISTENT_REQUIRE (rejected earlier with its own message)."],"exampleFix":"// before\nUtils::chooseHandler(['max_host_connections' => 6]);\n// RuntimeException: Connection cap options require a cap-capable cURL multi handler ...\n\n// after (option A: provide curl multi)\n//   docker-php-ext-install curl\n// after (option B: allow stream fallback)\n//   php.ini: allow_url_fopen = On\n// after (option C: drop caps)\nUtils::chooseHandler([]);","handlingStrategy":"validation","validationCode":"// Validate cap feasibility before requesting caps:\n$capCapable = function_exists('curl_multi_exec') || ini_get('allow_url_fopen');\n$opts = $capCapable ? ['max_host_connections' => 6] : []; // drop caps if not feasible\nUtils::chooseHandler($opts);","typeGuard":"function connectionCapsFeasible(): bool\n{\n    return function_exists('curl_multi_exec') || (bool) ini_get('allow_url_fopen');\n}","tryCatchPattern":"try {\n    $handler = Utils::chooseHandler(['max_host_connections' => 6]);\n} catch (\\RuntimeException $e) {\n    // Drop the caps and proceed without connection limits\n    $handler = Utils::chooseHandler([]);\n}","preventionTips":["Ensure curl_multi_exec exists in images that need caps, or enable allow_url_fopen as fallback.","Decide caps at deploy time from a capability probe, not hardcoded config.","Remember caps are incompatible with TransportSharing::PERSISTENT_REQUIRE."],"tags":["handler","curl","connection-limits","environment","configuration"],"analyzedSha":"9b200fc5805036b331d6031199880dadecae0275","analyzedAt":"2026-08-04T21:24:26.648Z","schemaVersion":2}