headroomlabs-ai/headroom · error · RuntimeError

Failed to download codebase-memory-mcp from {url}: {e}

Error message

Failed to download codebase-memory-mcp from {url}: {e}

What it means

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.

Source

Thrown at headroom/graph/installer.py:78

    """
    version = version or CBM_VERSION
    plat = _detect_platform()
    filename = f"codebase-memory-mcp-{plat}.tar.gz"
    url = f"{GITHUB_RELEASE_URL}/{version}/{filename}"

    CBM_BIN_DIR.mkdir(parents=True, exist_ok=True)
    target_path = CBM_BIN_DIR / CBM_BIN_NAME

    logger.info("Downloading codebase-memory-mcp %s for %s ...", version, plat)

    try:
        if not url.startswith(("http://", "https://")):
            raise ValueError(f"Invalid URL: {url}")

        with urlopen(url, timeout=60) as response:  # noqa: S310
            data = response.read()
    except Exception as e:
        raise RuntimeError(f"Failed to download codebase-memory-mcp from {url}: {e}") from e

    # Extract binary from tar.gz
    try:
        with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as tar:
            for member in tar.getmembers():
                if member.name.endswith(CBM_BIN_NAME) or member.name == CBM_BIN_NAME:
                    member.name = target_path.name
                    tar.extract(member, CBM_BIN_DIR)
                    break
            else:
                raise RuntimeError("codebase-memory-mcp binary not found in archive")
    except tarfile.TarError as e:
        raise RuntimeError(f"Failed to extract archive: {e}") from e

    # Make executable
    target_path.chmod(target_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)

    # Verify

View on GitHub (pinned to 322425c43b)

Solutions

  1. Read the chained cause (`except RuntimeError as e: e.__cause__`) — URLError vs HTTPError 404 points to network vs bad-version.
  2. 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.
  3. If network: fix proxy/DNS (HTTPS_PROXY) or retry when connectivity returns; the download step is safely retryable.
  4. Offline fallback: manually download the tar.gz, extract the binary onto PATH (get_cbm_path honors PATH first) so the installer is skipped.

Example fix

# before
try:
    install_cbm()
except RuntimeError as e:
    print(e)  # 'Failed to download ...: HTTP Error 404'

# after
try:
    install_cbm()
except RuntimeError as e:
    cause = e.__cause__
    if isinstance(cause, HTTPError) and cause.code == 404:
        install_cbm(version=CBM_LATEST_TAG)  # bad tag -> retry with known-good
    else:
        raise
Defensive patterns

Strategy: retry

Validate before calling

import socket, urllib.request

def github_reachable() -> bool:
    try:
        urllib.request.urlopen("https://github.com", timeout=5)
        return True
    except OSError:
        return False

assert github_reachable(), "no egress to github.com — CBM install will fail"

Try / catch

from urllib.error import HTTPError
import time

for attempt in range(3):
    try:
        install_cbm()
        break
    except RuntimeError as e:
        cause = e.__cause__
        if isinstance(cause, HTTPError) and cause.code == 404:
            raise RuntimeError("bad CBM version tag — check release assets") from e
        if attempt == 2:
            raise
        time.sleep(2 ** attempt)  # transient network: backoff and retry

Prevention

When it happens

Trigger: 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.

Common situations: First-run setup in a locked-down CI environment; air-gapped machines; pinned CBM_VERSION that no longer exists upstream; transient GitHub outages.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/36a9134de86fa98c. Report an issue: GitHub.