{"record":{"id":"36a9134de86fa98c","repo":"headroomlabs-ai/headroom","slug":"failed-to-download-codebase-memory-mcp-from-url","errorCode":null,"errorMessage":"Failed to download codebase-memory-mcp from {url}: {e}","messagePattern":"Failed to download codebase-memory-mcp from (.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"headroom/graph/installer.py","lineNumber":78,"sourceCode":"    \"\"\"\n    version = version or CBM_VERSION\n    plat = _detect_platform()\n    filename = f\"codebase-memory-mcp-{plat}.tar.gz\"\n    url = f\"{GITHUB_RELEASE_URL}/{version}/{filename}\"\n\n    CBM_BIN_DIR.mkdir(parents=True, exist_ok=True)\n    target_path = CBM_BIN_DIR / CBM_BIN_NAME\n\n    logger.info(\"Downloading codebase-memory-mcp %s for %s ...\", version, plat)\n\n    try:\n        if not url.startswith((\"http://\", \"https://\")):\n            raise ValueError(f\"Invalid URL: {url}\")\n\n        with urlopen(url, timeout=60) as response:  # noqa: S310\n            data = response.read()\n    except Exception as e:\n        raise RuntimeError(f\"Failed to download codebase-memory-mcp from {url}: {e}\") from e\n\n    # Extract binary from tar.gz\n    try:\n        with tarfile.open(fileobj=io.BytesIO(data), mode=\"r:gz\") as tar:\n            for member in tar.getmembers():\n                if member.name.endswith(CBM_BIN_NAME) or member.name == CBM_BIN_NAME:\n                    member.name = target_path.name\n                    tar.extract(member, CBM_BIN_DIR)\n                    break\n            else:\n                raise RuntimeError(\"codebase-memory-mcp binary not found in archive\")\n    except tarfile.TarError as e:\n        raise RuntimeError(f\"Failed to extract archive: {e}\") from e\n\n    # Make executable\n    target_path.chmod(target_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)\n\n    # Verify","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/graph/installer.py#L60-L96","documentation":"Wraps ANY exception from the codebase-memory-mcp download step (urlopen with a 60s timeout inside the try) into a RuntimeError with the URL and cause. Typical underlying causes: no network / DNS failure, a proxy blocking github.com, HTTP 404 because the version tag or platform asset does not exist, TLS problems, or a firewall resetting the connection. The chained exception (__cause__) preserves the real reason.","triggerScenarios":"install_cbm()/ensure flow while offline; version tag that has no release assets (typo'd or yanked release); GitHub rate-limiting or 5xx; corporate egress proxy rejecting the request; slow networks exceeding the 60-second read timeout.","commonSituations":"First-run setup in a locked-down CI environment; air-gapped machines; pinned CBM_VERSION that no longer exists upstream; transient GitHub outages.","solutions":["Read the chained cause (`except RuntimeError as e: e.__cause__`) — URLError vs HTTPError 404 points to network vs bad-version.","If 404: confirm the release tag and that an asset named codebase-memory-mcp-<plat>.tar.gz exists on the GitHub releases page; correct CBM_VERSION/version.","If network: fix proxy/DNS (HTTPS_PROXY) or retry when connectivity returns; the download step is safely retryable.","Offline fallback: manually download the tar.gz, extract the binary onto PATH (get_cbm_path honors PATH first) so the installer is skipped."],"exampleFix":"# before\ntry:\n    install_cbm()\nexcept RuntimeError as e:\n    print(e)  # 'Failed to download ...: HTTP Error 404'\n\n# after\ntry:\n    install_cbm()\nexcept RuntimeError as e:\n    cause = e.__cause__\n    if isinstance(cause, HTTPError) and cause.code == 404:\n        install_cbm(version=CBM_LATEST_TAG)  # bad tag -> retry with known-good\n    else:\n        raise","handlingStrategy":"retry","validationCode":"import socket, urllib.request\n\ndef github_reachable() -> bool:\n    try:\n        urllib.request.urlopen(\"https://github.com\", timeout=5)\n        return True\n    except OSError:\n        return False\n\nassert github_reachable(), \"no egress to github.com — CBM install will fail\"","typeGuard":null,"tryCatchPattern":"from urllib.error import HTTPError\nimport time\n\nfor attempt in range(3):\n    try:\n        install_cbm()\n        break\n    except RuntimeError as e:\n        cause = e.__cause__\n        if isinstance(cause, HTTPError) and cause.code == 404:\n            raise RuntimeError(\"bad CBM version tag — check release assets\") from e\n        if attempt == 2:\n            raise\n        time.sleep(2 ** attempt)  # transient network: backoff and retry","preventionTips":["Verify the release tag and its platform asset exist on GitHub before pinning CBM_VERSION.","Allow egress to github.com (or an internal mirror override) in CI images.","Cache/vendor the CBM binary on PATH for offline or rate-limited environments."],"tags":["network","download","installer","github","wrapping"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}