guzzle/guzzle · error · GuzzleHttp\Exception\RequestException
HTTP/3 is not supported by this cURL installation.
Error message
HTTP/3 is not supported by this cURL installation.
What it means
Thrown by getDefaultConf() when the request protocol version is HTTP/3 ('3' or '3.0') but the PHP cURL extension does not define CURL_HTTP_VERSION_3, meaning libcurl was not built with HTTP/3 support. HTTP/3 requires a specially built libcurl with a QUIC/HTTP3 backend (ngtcp2, quiche, etc.).
Source
Thrown at src/Handler/CurlFactory.php:2130
\CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
\CURLOPT_URL => (string) $uri->withFragment(''),
\CURLOPT_RETURNTRANSFER => false,
\CURLOPT_HEADER => false,
\CURLOPT_CONNECTTIMEOUT_MS => self::DEFAULT_CONNECT_TIMEOUT_MS,
];
if (CurlVersion::supportsProtocolsStr()) {
$conf[(int) \constant('CURLOPT_PROTOCOLS_STR')] = \implode(',', $protocols);
} else {
$conf[\CURLOPT_PROTOCOLS] = self::curlProtocolMask($protocols);
}
$version = $easy->request->getProtocolVersion();
$multiplex = self::normalizeMultiplex($easy->options);
if ('3' === $version || '3.0' === $version) {
if (!\defined('CURL_HTTP_VERSION_3')) {
throw new RequestException('HTTP/3 is not supported by this cURL installation.', $easy->request);
}
$proxy = ProxyEnv::resolveProxySelection($easy->request->getUri(), $easy->options['proxy'] ?? null);
if (\in_array($multiplex, [Multiplexing::REQUIRE_EAGER, Multiplexing::REQUIRE_WAIT], true)) {
self::assertSelectedProxySupported($proxy->getProxy(), $easy->request);
if ($proxy->hasProxy()) {
throw new RequestException('Required multiplexing cannot be guaranteed for HTTP/3 requests sent through a proxy.', $easy->request);
}
if (!CurlVersion::supportsRequiredHttp3Multiplex()) {
throw new RequestException('Required multiplexing for HTTP/3 needs libcurl 8.13.0 or newer built with HTTP/3 support.', $easy->request);
}
// HTTP/3 or fail: required multiplexing never downgrades, not
// even to HTTP/2.
$conf[\CURLOPT_HTTP_VERSION] = (int) \constant('CURL_HTTP_VERSION_3ONLY');
} else {
$conf[\CURLOPT_HTTP_VERSION] = $proxy->hasProxy()View on GitHub (pinned to 9b200fc580)
Solutions
- Use HTTP/2 ('2' or '2.0') instead, which is widely supported and negotiates with HTTP/3-capable servers via Alt-Svc.
- Install a libcurl build with HTTP/3 support (e.g. compiled with ngtcp2/quiche) and rebuild the PHP cURL extension.
- Remove the 'version' => '3' option and let Guzzle/libcurl negotiate.
Example fix
// before $client->get($url, ['version' => '3']); // after $client->get($url, ['version' => '2']);
Defensive patterns
Strategy: validation
Validate before calling
if (($options['version'] ?? null) === '3' && !defined('CURL_HTTP_VERSION_3')) {
throw new \RuntimeException('HTTP/3 not supported by this cURL build; use version 2 or upgrade libcurl.');
} Type guard
function libcurlSupportsHttp3(): bool { return defined('CURL_HTTP_VERSION_3'); } Try / catch
try {
$client->get($url, ['version' => '3']);
} catch (\GuzzleHttp\Exception\RequestException $e) {
// Fall back to HTTP/2 or upgrade libcurl.
} Prevention
- Detect CURL_HTTP_VERSION_3 at boot before setting version 3.
- Default to HTTP/2 for broad compatibility with HTTP/3 servers via Alt-Svc.
When it happens
Trigger: Calling $client->get($url, ['version' => '3']) (or 3.0) on a standard libcurl build without HTTP/3 support.
Common situations: Most default libcurl installations lack HTTP/3; requesting version 3 because the server supports it without checking the client; testing HTTP/3 in CI with a stock image.
Related errors
- Required multiplexing for HTTP/3 needs libcurl 8.13.0 or new
- HTTP/3 is supported by the cURL handler, however the install
- Tunneling requests through an HTTP proxy is not supported by
- Required multiplexing cannot be guaranteed for HTTP/3 reques
- The "multiplex" request option cannot be required for HTTP/%
AI-assisted analysis of guzzle/guzzle@9b200fc580 (2026-08-04).
Data as JSON: /data/errors/7afbc02cc0bb0765.json.
Report an issue: GitHub.