Composer "The ... file could not be downloaded" - Network Failures in CI
By Daniel Zoghalchali·Latchkey
Composer’s connection to Packagist or a package’s download URL stalled or dropped. These are transient network failures and almost always succeed on retry.
What this error means
Composer fails partway through fetching package metadata or a dist archive with "file could not be downloaded" or a curl timeout. Re-running the job usually works with no change - the hallmark of a transient network issue.
composer output
- Downloading symfony/console (v7.1.0)
The "https://api.github.com/repos/symfony/console/zipball/abc123" file could not
be downloaded (HTTP/2 0 ): Failed to connect to api.github.com port 443
[curl error 28] Operation timed out after 30000 milliseconds
Diagnose it: platform requirements and auth
Composer resolves against the PHP version and extensions actually present, so a lockfile that installs locally can be unsatisfiable on a runner with a different PHP build.
Terminal
php -v && php -m | head -30
composer diagnose
composer check-platform-reqs
# install exactly what is locked, non-interactively
composer install --no-interaction --prefer-dist --no-progress
Common causes
Transient network or mirror slowness
A brief connectivity blip, an overloaded Packagist mirror, or a slow GitHub zipball endpoint causes the download to time out. Nothing is wrong with your project.
Unauthenticated GitHub API rate limiting
Without a GitHub token, Composer hits GitHub’s low anonymous rate limit and downloads start failing with 403/timeout under load.
How to fix it
Retry and prefer dist archives
Composer retries automatically, but you can re-run the install step and prefer cached dist downloads.
Terminal
composer install --no-interaction --prefer-dist
# simple retry wrapper
for i in 1 2 3; do composer install --no-interaction && break; sleep 5; done
Authenticate GitHub to avoid rate limits
Provide a token so Composer uses the authenticated, higher rate limit.
Provide a github-oauth token in CI to avoid anonymous rate limits.
Use --prefer-dist so installs pull stable, cacheable archives.
Frequently asked questions
What causes Composer "The ... file could not be downloaded"?
There are 2 common causes: transient network or mirror slowness and unauthenticated github api rate limiting. A brief connectivity blip, an overloaded Packagist mirror, or a slow GitHub zipball endpoint causes the download to time out.
How do I fix Composer "The ... file could not be downloaded"?
There are 3 fixes depending on which cause you have: retry and prefer dist archives, authenticate github to avoid rate limits, and cache the composer cache between runs. Work through them in order, since the first is the most common.
What does Composer "The ... file could not be downloaded" actually mean?
Composer fails partway through fetching package metadata or a dist archive with "file could not be downloaded" or a curl timeout.
How do I stop Composer "The ... file could not be downloaded" happening again?
Cache the Composer cache keyed on composer.lock. The prevention section lists 3 changes that keep it from recurring.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.
This is a transient network failure, not a bug in your code. Latchkey detects, repairs, and retries it for you.Start free →30-day trial · No credit card
Cookie Preferences
Choose which categories of cookies you want to allow. Essential cookies are always active as they are required for the site to function.
Essential
Required for the site to function.
Functional
Remembers your preferences like selected organization and dashboard settings.
Analytics
Helps us understand how the site is used (Google Analytics).