{"record":{"id":"369d8f35054e5237","repo":"dbt-labs/dbt-core","slug":"failed-to-download-url-last","errorCode":null,"errorMessage":"failed to download {url}: {last}","messagePattern":"failed to download (.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"crates/dbt-ci/templates/sdist_build_backend.py","lineNumber":92,"sourceCode":"            tty.write(text + \"\\n\\n\\n\")\n    except (OSError, ValueError):\n        pass\n\n\ndef _fetch(url):\n    last = None\n    for attempt in range(1, _RETRIES + 1):\n        try:\n            req = urllib.request.Request(\n                url, headers={\"User-Agent\": \"{}-sdist\".format(_MANIFEST[\"name\"])}\n            )\n            with urllib.request.urlopen(req, timeout=_TIMEOUT) as resp:\n                return resp.read()\n        except (urllib.error.URLError, TimeoutError, OSError) as exc:\n            last = exc\n            if attempt < _RETRIES:\n                time.sleep(2 ** (attempt - 1))\n    raise RuntimeError(f\"failed to download {url}: {last}\")\n\n\ndef build_wheel(wheel_directory, config_settings=None, metadata_directory=None):\n    _emit_notice()\n    entry = _select_wheel()\n    filename = entry[\"filename\"]\n    url = \"{base}/{file}\".format(base=_MANIFEST[\"base_url\"].rstrip(\"/\"), file=filename)\n    data = _fetch(url)\n\n    digest = hashlib.sha256(data).hexdigest()\n    if digest != entry[\"sha256\"]:\n        raise RuntimeError(\n            f\"sha256 mismatch for {filename}: expected {entry['sha256']}, got {digest}\"\n        )\n\n    out = Path(wheel_directory) / filename\n    out.write_bytes(data)\n    return filename","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-ci/templates/sdist_build_backend.py#L74-L110","documentation":"`_fetch` downloads the prebuilt wheel from the manifest's `base_url` with up to `_RETRIES` (4) attempts and exponential backoff. If every attempt fails with URLError, TimeoutError, or OSError, it raises RuntimeError including the URL and the last exception. It exists because the sdist ships no code — the wheel must be fetched at install time.","triggerScenarios":"`build_wheel` (via `_fetch`) cannot download `{base_url}/{filename}`: DNS failure, no network, proxy/firewall blocking, HTTP 4xx/5xx surfacing as URLError (e.g. HTTPError), asset missing from the release store, or all attempts timing out after 60s each.","commonSituations":"CI runners without internet egress or behind a corporate proxy; the release asset was deleted or never uploaded; transient registry/CDN outage exhausting the 4 retries; TLS interception producing SSL errors.","solutions":["Check network connectivity and proxy settings (HTTPS_PROXY/HTTP_PROXY) in the install environment","Verify the URL from the error message is reachable (curl it) — if 404, the release asset is missing","Retry the install later if it's a transient CDN/network outage","Pre-download the wheel and install it directly, or use a mirror of the release assets","Use a release version whose assets are confirmed published"],"exampleFix":"# before (no egress in CI)\npip install mypkg\n# after\nexport HTTPS_PROXY=http://proxy.corp:3128\npip install mypkg","handlingStrategy":"retry","validationCode":"import urllib.request\ndef url_reachable(url: str) -> bool:\n    try:\n        return urllib.request.urlopen(url, timeout=10).status == 200\n    except Exception:\n        return False\n# check base_url + filename before installing","typeGuard":null,"tryCatchPattern":"try:\n    build_wheel(wheel_dir)\nexcept RuntimeError as e:\n    if 'failed to download' in str(e):\n        time.sleep(30)\n        build_wheel(wheel_dir)  # retry once on transient network failure\n    else:\n        raise","preventionTips":["Ensure install environments (CI runners) have egress or correct proxy env vars","Pre-download wheels and install from local files in air-gapped setups","Verify release assets are published before announcing/releasing a version","Retry transient failures; the backend already backs off 4 times"],"tags":["network","download","pip","timeout"],"backgroundTag":"network-request-failed","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}