dotnet/runtime · 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 gives up after max_retries (default 3) attempts that all failed with timeouts, aiohttp ClientErrors, or non-200 responses. The exception bubbles out of asyncio.gather and aborts the whole rootfs build, because missing even one .deb would leave the rootfs unusable.

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 60108ba66e)

Solutions

  1. Check outbound connectivity to the mirror from the build host (curl/GET the URL).
  2. Increase max_retries and retry_delay by editing the call, or retry the whole build later.
  3. Switch --mirror to a reachable mirror (official Debian/Ubuntu, internal mirror, or a local apt-cacher).
  4. If a proxy is required, configure HTTPS_PROXY/HTTP_PROXY for the build.

Example fix

# before
python3 install-debs.py --arch arm64 ... # network down, all 3 retries fail

# after
export HTTPS_PROXY=http://corp-proxy:8080
python3 install-debs.py --arch arm64 ... # or wait for mirror recovery and rerun
Defensive patterns

Strategy: retry

Validate before calling

# Pre-flight connectivity check before running install-debs.py.
import socket, sys
host = 'deb.debian.org'
try:
    socket.create_connection((host, 443), timeout=5).close()
except OSError:
    print(f'No route to {host}; configure proxy or pick reachable --mirror'); sys.exit(2)

Try / catch

# Wrap the top-level invocation; download_file has exhausted its own retries.
import subprocess, sys
for attempt in range(3):
    rc = subprocess.call([sys.executable, 'install-debs.py', *args])
    if rc == 0:
        break
    if attempt == 2:
        print('All rootfs build attempts failed; check mirror/proxy/network.')
        sys.exit(rc)

Prevention

When it happens

Trigger: All retry attempts in the download_file loop fail (network down, mirror unreachable, persistent 4xx/5xx, TLS errors, or repeated checksum failures). Raised at install-debs.py:47 after the loop exits.

Common situations: CI runner without outbound network to the mirror. Mirror is down or under maintenance. DNS resolution failure. Corporate firewall blocking the mirror. Transient outage lasting longer than retries*retry_delay.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/f46d752671928926. Report an issue: GitHub.