composer/composer · error · RuntimeException
Failed getting info from curl handle {i} ({url})
Error message
Failed getting info from curl handle {i} ({url}) What it means
Thrown when curl_getinfo() returns false for a curl easy-handle inside the multi-exec processing loop of CurlDownloader. Composer relies on curl_getinfo to read transfer metadata (HTTP code, size, timing) before rejecting/completing a job; a false return means the underlying libcurl handle is no longer queryable, so Composer cannot continue safely. The message includes the internal handle id ($i) and the sanitized URL so you can identify which request failed. This is a low-level libcurl/PHP interop failure rather than a normal HTTP error.
Source
Thrown at src/Composer/Util/Http/CurlDownloader.php:361
$active = true;
$this->checkCurlResult(curl_multi_exec($this->multiHandle, $active));
if (-1 === curl_multi_select($this->multiHandle, $this->selectTimeout)) {
// sleep in case select returns -1 as it can happen on old php versions or some platforms where curl does not manage to do the select
usleep(150);
}
while ($progress = curl_multi_info_read($this->multiHandle)) {
$curlHandle = $progress['handle'];
$result = $progress['result'];
$i = (int) $curlHandle;
if (!isset($this->jobs[$i])) {
continue;
}
$progress = curl_getinfo($curlHandle);
if (false === $progress) {
throw new \RuntimeException('Failed getting info from curl handle '.$i.' ('.Url::sanitize($this->jobs[$i]['url']).')');
}
$job = $this->jobs[$i];
unset($this->jobs[$i]);
$error = curl_error($curlHandle);
$errno = curl_errno($curlHandle);
curl_multi_remove_handle($this->multiHandle, $curlHandle);
if (\PHP_VERSION_ID < 80000) {
curl_close($curlHandle);
}
$headers = null;
$statusCode = null;
$response = null;
try {
// TODO progress
if (CURLE_OK !== $errno || $error || $result !== CURLE_OK) {
$errno = $errno ?: $result;
if (!$error && function_exists('curl_strerror')) {View on GitHub (pinned to 6ffc117740)
Solutions
- Update PHP and the php-curl/libcurl extension to the latest patch release for your PHP version.
- Check COMPOSER_CAFILE / openssl CA bundle and proxy env vars (HTTP_PROXY/HTTPS_PROXY) for corruption that could destabilize transfers.
- Reproduce with `composer <command> -vvv` to capture the exact URL/handle, then disable parallel downloads via COMPOSER_MAX_PARALLEL_HTTP=1 to rule out multi-handle races.
- If it persists on a specific URL, test that URL directly with curl on the host to isolate a libcurl-level fault.
Example fix
// before (env instability) COMPOSER_MAX_PARALLEL_HTTP=50 composer install // after (isolate multi-handle races, upgrade path) COMPOSER_MAX_PARALLEL_HTTP=1 composer install -vvv
Defensive patterns
Strategy: retry
Validate before calling
// Cannot fully prevent (libcurl-internal); validate transport health before the run.
if (!extension_loaded('curl')) { throw new \RuntimeException('php-curl extension required'); }
if (!is_callable('curl_multi_init')) { throw new \RuntimeException('curl multi support missing'); } Try / catch
try { $response = $httpDownloader->get($url); } catch (\RuntimeException $e) {
if (str_starts_with($e->getMessage(), 'Failed getting info from curl handle')) {
// transient libcurl state — retry once after reset, then surface
$httpDownloader->reset(); $response = $httpDownloader->get($url);
} else { throw $e; }
} Prevention
- Keep php-curl/libcurl patched to current stable.
- Set COMPOSER_MAX_PARALLEL_HTTP=1 when debugging multi-handle issues.
- Avoid forking the PHP process while Composer's curl handles are live.
When it happens
Trigger: Occurs in CurlDownloader::select()/loop when curl_multi_info_read yields a finished handle but curl_getinfo on that handle returns false — typically when the handle was already closed, the multi-handle is in a bad state, or libcurl hit an internal error mid-transfer.
Common situations: Hitting this during a `composer install/update` behind a flaky proxy, after a process fork that duplicated curl handles, on PHP versions with libcurl bugs, or when a custom transport/curl option conflicts with Composer's multi-handle. Rare in normal use; usually signals a corrupted curl session or environment (e.g. outdated php-curl extension).
Related errors
- cURL error: {code} ({errorName}): cURL message: {curlMessage
- $url must not be an empty string
- Your configuration does not allow connections to {url}. See
- Your configuration does not allow connections to {url}. See
- Failed to execute {command} {errorOutput}
AI-assisted analysis of composer/composer@6ffc117740 (2026-08-07).
Data as JSON: /api/errors/1461402a359301b0.
Report an issue: GitHub.