dotnet/efcore · error · Exception
Failed to download {url}, Status Code: {response.status}
Error message
Failed to download {url}, Status Code: {response.status} What it means
Raised by download_file when the HTTP response status is anything other than 200. The exception is thrown inside the per-attempt try block, so unlike network errors it is NOT caught by the (CancelledError, TimeoutError, ClientError) handler and propagates immediately without consuming the retry budget. It signals that the server answered but refused/failed the request (404, 403, 5xx, etc.).
Source
Thrown at eng/common/cross/install-debs.py:40
attempt = 0
while attempt < max_retries:
try:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=timeout)) as response:
if response.status == 200:
with open(dest_path, "wb") as f:
content = await response.read()
# 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:View on GitHub (pinned to dbf9771522)
Solutions
- Open the exact {url} from the message in a browser or with `curl -I` to confirm the status code and the mirror's actual layout.
- Re-check the --suite and --arch arguments against the mirror's dists/<suite>/ and binary-<arch> directory names.
- Verify the --mirror URL is the correct base for the distro (Debian vs Debian-ports vs Ubuntu) and has no trailing/missing path segment.
- If the mirror is returning 5xx, switch to another mirror or retry later.
Example fix
# before python install-debs.py --mirror http://ftp.debian.org/debian --arch loong64 --suite sid ... # after (loong64 lives in debian-ports, not debian) python install-debs.py --mirror http://ftp.ports.debian.org/debian-ports --arch loong64 --suite sid ...
Defensive patterns
Strategy: try-catch
Validate before calling
# Validate the URL is reachable and returns 200 before relying on download_file
import aiohttp, asyncio
async def check_url(url, timeout=30):
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=timeout)) as s:
async with s.get(url) as r:
if r.status != 200:
raise RuntimeError(f"{url} -> HTTP {r.status}; fix mirror/suite/arch before downloading")
return True
asyncio.run(check_url(f"{mirror}/dists/{suite}/main/binary-{arch}/Packages.gz")) Try / catch
# download_file raises bare Exception with the message; match on the prefix
try:
await download_file(session, url, dest_path, checksum=checksum)
except Exception as e:
msg = str(e)
if msg.startswith("Failed to download") and "Status Code" in msg:
# HTTP-level failure: do NOT blind-retry, fix the URL/suite/arch
raise SystemExit(f"Mirror returned non-200 for {url}: {msg}")
raise Prevention
- Resolve --mirror, --suite, --arch against the mirror's actual directory layout before running.
- Use curl -I on the would-be Packages.gz and .deb URLs in CI smoke checks.
- Prefer a canonical mirror over a random one; document the exact mirror per distro in your build config.
When it happens
Trigger: Calling download_file / download_deb_files_parallel / download_package_index_parallel where session.get(url) returns a non-200 status. Concretely: a missing Packages.gz under the given --suite/--arch (404), a forbidden mirror path (403), or a mirror/server error (500/502/503).
Common situations: Wrong --mirror base URL; --suite or --arch typo (e.g. 'sid' vs 'unstable', 'loong64' vs 'loongarch64'); component path not present on the mirror (e.g. requesting 'universe' on a Debian mirror); package Filename in the index pointing to a file the mirror no longer serves; mirror under maintenance returning 503.
Related errors
- SHA256 mismatch for {url}: expected {checksum}, got {sha256}
- Failed to download {url} after {max_retries} attempts.
- Could not find checksum for {path} in Release file.
- Invalid number of index sort order values: {numValues} value
- IsDescending and AllDescending cannot both be specified on t
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/437087a09524af21.
Report an issue: GitHub.