{"record":{"id":"91b0071959ece52a","repo":"dotnet/efcore","slug":"failed-to-download-url-after-max-retries-attem","errorCode":null,"errorMessage":"Failed to download {url} after {max_retries} attempts.","messagePattern":"Failed to download (.+?) after (.+?) attempts\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"eng/common/cross/install-debs.py","lineNumber":47,"sourceCode":"\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:\n                url = f\"{mirror}/{filename}\"\n                dest_path = os.path.join(tmp_dir, os.path.basename(filename))\n                tasks.append(asyncio.create_task(download_file(session, url, dest_path, checksum=info.get(\"SHA256\"))))\n\n        await asyncio.gather(*tasks)\n\nasync def download_package_index_parallel(mirror, arch, suites, check_sig, keyring):","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/eng/common/cross/install-debs.py#L29-L65","documentation":"Raised by download_file after the while loop exhausts max_retries (default 3). It is only reached for the retryable exception types asyncio.CancelledError, asyncio.TimeoutError, and aiohttp.ClientError; integrity (620) and non-200 (621) failures bypass it. It is the terminal 'I retried and gave up' error for network-layer problems.","triggerScenarios":"Every attempt failed with a connection/timeout/DNS error (aiohttp.ClientError or asyncio.TimeoutError) for max_retries consecutive tries with retry_delay seconds between them.","commonSituations":"No or flaky network, mirror is down or rate-limiting, DNS misconfigured, firewall blocking the mirror, or the default 60s timeout is too short for a large .deb over a slow link.","solutions":["Check connectivity to the mirror: curl -I {mirror}.","Increase timeout and retries by passing max_retries/timeout at the call site in download_deb_files_parallel (the CLI does not expose them).","Switch to a closer/official mirror or a snapshot mirror.","Fix DNS and HTTP_PROXY/HTTPS_PROXY environment.","Reduce parallelism if the mirror is rate-limiting connections."],"exampleFix":"// before\ntasks.append(asyncio.create_task(download_file(session, url, dest_path, checksum=info.get(\"SHA256\"))))\n\n// after\ntasks.append(asyncio.create_task(download_file(session, url, dest_path, max_retries=5, retry_delay=5, timeout=180, checksum=info.get(\"SHA256\"))))","handlingStrategy":"retry","validationCode":"# preflight: basic reachability of the mirror before starting downloads\nimport urllib.request\ntry:\n    with urllib.request.urlopen(f\"{mirror}/\", timeout=10) as r:\n        assert r.status == 200\nexcept Exception:\n    sys.exit(\"mirror unreachable, fix network/DNS/proxy before running\")","typeGuard":null,"tryCatchPattern":"for run in range(3):\n    try:\n        asyncio.run(install_packages(...))\n        break\n    except Exception as e:\n        if \"after\" in str(e) and \"attempts\" in str(e):\n            continue  # network exhaustion -> back off and retry the whole pipeline\n        raise\nelse:\n    raise SystemExit(\"downloads failed after repeated full-run retries\")","preventionTips":["Run on a stable network link; configure HTTP_PROXY/HTTPS_PROXY correctly.","Use a geo-local or official mirror to reduce timeouts.","If on a slow link, raise the timeout/max_retries at the download_file call site."],"tags":["network","retry","timeout","deb"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}