dotnet/yarp · error · Exception
Failed to download {url} after {max_retries} attempts.
Error message
Failed to download {url} after {max_retries} attempts. What it means
This exception is raised at the bottom of download_file after the retry loop exhausts all max_retries (default 3) attempts. It is only reached when every attempt failed with an exception type listed in the except clause: asyncio.CancelledError, asyncio.TimeoutError, or aiohttp.ClientError (connection refused, DNS failure, SSL error, etc.). Note that HTTP non-200 responses raise a different exception (error 103) that bypasses this path entirely because it is not caught by the except clause.
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 bd11867bee)
Solutions
- Verify network connectivity to the mirror: run curl -v <mirror-url> or ping the mirror host to confirm reachability.
- Increase max_retries and retry_delay in the download_file call (e.g. max_retries=5, retry_delay=5) if the mirror is intermittently available.
- Check DNS resolution: ensure the mirror hostname resolves correctly (dig <hostname> or nslookup).
- If behind a corporate proxy, set the HTTPS_PROXY / HTTP_PROXY environment variables so aiohttp routes through it.
- Increase the per-request timeout (currently 60s) if downloading large .deb files from a slow mirror.
- Switch to a faster, closer, or more reliable mirror.
Example fix
# before -- default retry parameters may be too conservative
tasks.append(asyncio.create_task(download_file(session, url, dest_path, checksum=info.get("SHA256"))))
# after -- pass more generous retry parameters for flaky mirrors
tasks.append(asyncio.create_task(
download_file(session, url, dest_path,
max_retries=5, retry_delay=5, timeout=120,
checksum=info.get("SHA256")))) Defensive patterns
Strategy: retry
Validate before calling
# Pre-check network connectivity and DNS before starting downloads.
import socket, urllib.parse
parsed = urllib.parse.urlparse(mirror)
try:
socket.gethostbyname(parsed.hostname)
print(f"DNS resolves for {parsed.hostname}")
except socket.gaierror:
print(f"ERROR: Cannot resolve {parsed.hostname}. Check DNS or mirror URL.") Try / catch
# Catch the final failure and provide a clear diagnostic with retry guidance
try:
await asyncio.gather(*tasks)
except Exception as e:
if 'after' in str(e) and 'attempts' in str(e):
print(f"All retries exhausted. Possible causes: network down, DNS failure, "
f"TLS error, or mirror unreachable.")
print(f"Try: increasing max_retries, checking proxy settings, or switching mirrors.")
raise Prevention
- Set generous retry parameters (max_retries=5, retry_delay=5, timeout=120) for unreliable networks.
- Verify DNS resolution and network reachability of the mirror before starting the build.
- If behind a corporate proxy, set HTTP_PROXY/HTTPS_PROXY environment variables.
- Use a mirror geographically close to reduce latency and timeout risk.
- Monitor download progress to detect stalls early.
When it happens
Trigger: download_file's while loop (lines 23-45) iterates max_retries times (default 3). On each attempt, session.get raises asyncio.TimeoutError (the 60-second timeout fires), aiohttp.ClientConnectorError (DNS resolution failure, connection refused, TLS handshake failure), or asyncio.CancelledError. After all attempts, control falls through to line 47 and raises this final exception.
Common situations: DNS resolution failure for the mirror hostname; the mirror host is unreachable (firewall, network partition, VPN routing issue); TLS/SSL certificate problems causing handshake failures; the default 60-second timeout is too short for a slow mirror or large packages; all connection attempts time out behind a restrictive corporate proxy; the mirror is down or rate-limiting all connections; retry_delay (2 seconds) is too short for the mirror to recover between attempts.
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/yarp@bd11867bee (2026-08-13).
Data as JSON: /api/errors/a7e169ff3c499d89.
Report an issue: GitHub.