{"record":{"id":"437087a09524af21","repo":"dotnet/efcore","slug":"failed-to-download-url-status-code-response-s","errorCode":null,"errorMessage":"Failed to download {url}, Status Code: {response.status}","messagePattern":"Failed to download (.+?), Status Code: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"eng/common/cross/install-debs.py","lineNumber":40,"sourceCode":"    attempt = 0\n    while attempt < max_retries:\n        try:\n            async with session.get(url, timeout=aiohttp.ClientTimeout(total=timeout)) as response:\n                if response.status == 200:\n                    with open(dest_path, \"wb\") as f:\n                        content = await response.read()\n\n                        # verify checksum if provided\n                        if checksum:\n                            sha256 = hashlib.sha256(content).hexdigest()\n                            if sha256 != checksum:\n                                raise Exception(f\"SHA256 mismatch for {url}: expected {checksum}, got {sha256}\")\n\n                        f.write(content)\n                    print(f\"Downloaded {url} at {dest_path}\")\n                    return\n                else:\n                    raise Exception(f\"Failed to download {url}, Status Code: {response.status}\")\n        except (asyncio.CancelledError, asyncio.TimeoutError, aiohttp.ClientError) as e:\n            print(f\"Error downloading {url}: {type(e).__name__} - {e}. Retrying...\")\n\n        attempt += 1\n        await asyncio.sleep(retry_delay)\n\n    raise Exception(f\"Failed to download {url} after {max_retries} attempts.\")\n\nasync def download_deb_files_parallel(mirror, packages, tmp_dir):\n    \"\"\"Download .deb files in parallel.\"\"\"\n    os.makedirs(tmp_dir, exist_ok=True)\n\n    tasks = []\n    timeout = aiohttp.ClientTimeout(total=60)\n    async with aiohttp.ClientSession(timeout=timeout) as session:\n        for pkg, info in packages.items():\n            filename = info.get(\"Filename\")\n            if filename:","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/eng/common/cross/install-debs.py#L22-L58","documentation":"Raised by download_file when the HTTP response status is anything other than 200. Like the SHA256 case it is a bare Exception, so it escapes the retry except clause and fails immediately: a 404/403/500 is NOT retried despite the retry loop.","triggerScenarios":"session.get(url) returns a non-200 status for a .deb URL built as {mirror}/{info['Filename']}. Typical when the Packages index references a file path the mirror does not actually serve.","commonSituations":"--suite/--arch/--mirror mismatch (index from one suite, files from another), package removed from the suite, mirror temporarily returning 5xx, arch not published on that mirror, or a redirect to an HTML error page that aiohttp did not follow.","solutions":["Open {mirror}/{filename} in a browser or curl -I it to see the real status code and body.","Confirm --mirror, --suite, and --arch form a valid combination (e.g. the arch exists for that suite).","Try a different, official mirror.","If the status is 5xx, wait and re-run the whole pipeline later.","Check HTTP_PROXY/HTTPS_PROXY env vars are not routing to a broken proxy."],"exampleFix":"// before\nelse:\n    raise Exception(f\"Failed to download {url}, Status Code: {response.status}\")  # not retried\n\n// after\nelse:\n    # raise a type the except clause covers so the retry loop actually engages\n    raise aiohttp.ClientError(f\"HTTP {response.status} for {url}\")","handlingStrategy":"retry","validationCode":"# preflight: HEAD one package URL to confirm the mirror serves it before the full run\nimport aiohttp\nasync def head_ok(mirror, filename):\n    async with aiohttp.ClientSession() as s:\n        async with s.get(f\"{mirror}/{filename}\") as r:\n            return r.status == 200\n# if not asyncio.run(head_ok(args.mirror, sample_filename)): sys.exit('mirror cannot serve debs')","typeGuard":null,"tryCatchPattern":"try:\n    asyncio.run(download_deb_files_parallel(mirror, packages, tmp_dir))\nexcept Exception as e:\n    if \"Status Code\" in str(e):\n        raise SystemExit(f\"mirror returned non-200, check mirror/suite/arch: {e}\")\n    raise","preventionTips":["Validate that --mirror, --suite, and --arch correspond to a published combination before running.","Prefer official mirrors over community ones that may prune old packages.","Clear HTTP_PROXY/HTTPS_PROXY if a proxy is rewriting responses."],"tags":["network","http","deb","mirror"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}