dotnet/aspnetcore · error · Exception
Failed to download {url} after {max_retries} attempts.
Error message
Failed to download {url} after {max_retries} attempts. What it means
download_file retries up to max_retries (default 3) but only catches asyncio.CancelledError, asyncio.TimeoutError, and aiohttp.ClientError. If all attempts fail with one of those exception types, the loop exhausts and raises a final Exception naming the URL and attempt count. This is the terminal failure for transient network problems that did not self-heal within the retry budget.
Source
Thrown at eng/common/cross/install-debs.py:47
# verify checksum if provided
if checksum:
sha256 = hashlib.sha256(content).hexdigest()
if sha256 != checksum:
raise Exception(f"SHA256 mismatch for {url}: expected {checksum}, got {sha256}")
f.write(content)
print(f"Downloaded {url} at {dest_path}")
return
else:
raise Exception(f"Failed to download {url}, Status Code: {response.status}")
except (asyncio.CancelledError, asyncio.TimeoutError, aiohttp.ClientError) as e:
print(f"Error downloading {url}: {type(e).__name__} - {e}. Retrying...")
attempt += 1
await asyncio.sleep(retry_delay)
raise Exception(f"Failed to download {url} after {max_retries} attempts.")
async def download_deb_files_parallel(mirror, packages, tmp_dir):
"""Download .deb files in parallel."""
os.makedirs(tmp_dir, exist_ok=True)
tasks = []
timeout = aiohttp.ClientTimeout(total=60)
async with aiohttp.ClientSession(timeout=timeout) as session:
for pkg, info in packages.items():
filename = info.get("Filename")
if filename:
url = f"{mirror}/{filename}"
dest_path = os.path.join(tmp_dir, os.path.basename(filename))
tasks.append(asyncio.create_task(download_file(session, url, dest_path, checksum=info.get("SHA256"))))
await asyncio.gather(*tasks)
async def download_package_index_parallel(mirror, arch, suites, check_sig, keyring):View on GitHub (pinned to 294cab2f9b)
Solutions
- Verify outbound connectivity from the host: curl -I <mirror-url> before re-running.
- Set correct HTTP_PROXY/HTTPS_PROXY/NO_PROXY environment variables if behind a corporate proxy, or unset them if they are wrong.
- Increase robustness by passing a larger max_retries/retry_delay to download_file (requires code change) for flaky links.
- Switch to a mirror reachable from the build environment (e.g., a locally mirrored copy or snapshot.debian.org).
- If building in CI, confirm the runner has network access and is not sandboxed to a package allowlist.
Example fix
# before — running with no proxy in a corporate network HTTPS_PROXY=http://dead-proxy:8080 python3 install-debs.py ... # Failed to download after 3 attempts # after unset HTTPS_PROXY HTTP_PROXY python3 install-debs.py --mirror http://deb.debian.org/debian ...
Defensive patterns
Strategy: retry
Validate before calling
# Verify connectivity before invoking install-debs
import socket
host = urllib.parse.urlparse(mirror).hostname
try:
socket.create_connection((host, 443), timeout=5).close()
except OSError:
raise SystemExit(f'No route to mirror {host}; fix network/proxy first') Try / catch
# download_file only catches transient errors; wrap the whole gather for resilience
import asyncio
for attempt in range(3):
try:
await asyncio.gather(*tasks)
break
except Exception as e:
if 'after' in str(e) and 'attempts' in str(e):
print(f'All retries exhausted ({attempt+1}/3); switching mirror or backoff')
await asyncio.sleep(2 ** attempt)
continue
raise Prevention
- Confirm outbound connectivity (DNS, proxy, firewall) before running.
- Set HTTP_PROXY/HTTPS_PROXY correctly in corporate networks, or unset them when wrong.
- For flaky links, raise max_retries/retry_delay in download_file.
- Use a local mirror to remove network as a variable.
When it happens
Trigger: Sustained DNS failure, connection refused, TLS handshake error, or read timeout that persists across all 3 attempts spaced retry_delay (default 2s) apart. Each failure prints 'Error downloading ... Retrying...' and the loop increments attempt. After the final failure, this exception is raised and aborts asyncio.gather.
Common situations: No network egress from the build host to the mirror; DNS misconfigured in the build container; mirror is down or unreachable; firewall blocking outbound HTTPS; proxy environment variables (HTTP_PROXY/HTTPS_PROXY) point at a dead proxy.
Related errors
- SHA256 mismatch for {url}: expected {checksum}, got {sha256}
- Failed to download {url}, Status Code: {response.status}
- SHA256 mismatch for {path}: expected {packages_sha}, got {sh
- Signature verification failed: {result.stderr.decode('utf-8'
- Could not find checksum for {path} in Release file.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/6b10c30ff60cbd35.
Report an issue: GitHub.