headroomlabs-ai/headroom · error · RuntimeError

codebase-memory-mcp binary not found in archive

Error message

codebase-memory-mcp binary not found in archive

What it means

Raised when the downloaded codebase-memory-mcp tar.gz opened successfully but no archive member matches the binary name (checked via member.name.endswith(CBM_BIN_NAME) or exact equality). It means the download itself succeeded but the archive layout is not what the installer expects — e.g. a wrong asset for the platform, an HTML error page saved as .tar.gz by a redirecting proxy, or an upstream packaging change that renamed the inner binary.

Source

Thrown at headroom/graph/installer.py:89

    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
    try:
        from headroom._subprocess import run

        result = run(
            [str(target_path), "--version"],
            capture_output=True,
            text=True,
        )
        if result.returncode == 0:
            ver = result.stdout.strip()
            logger.info("Installed: %s", ver)

View on GitHub (pinned to 322425c43b)

Solutions

  1. Download the URL manually and inspect: tar -tzf codebase-memory-mcp-<plat>.tar.gz — see what the inner binary is actually named.
  2. If the name changed upstream, update CBM_BIN_NAME or upgrade headroom to a release matching the new layout.
  3. If the 'archive' is HTML, fix the proxy/egress path — the URL is probably being redirected.
  4. As a workaround, extract the correct binary manually and place it on PATH so the installer is bypassed.

Example fix

# before
# RuntimeError: codebase-memory-mcp binary not found in archive

# after: inspect then work around
$ tar -tzf codebase-memory-mcp-linux-amd64.tar.gz   # confirm inner name
$ tar -xzf codebase-memory-mcp-linux-amd64.tar.gz -C ~/.local/bin/
$ chmod +x ~/.local/bin/codebase-memory-mcp   # PATH lookup then short-circuits install
Defensive patterns

Strategy: fallback

Validate before calling

import io, tarfile

def archive_has_binary(data: bytes, bin_name: str) -> bool:
    try:
        with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as tar:
            return any(m.name.endswith(bin_name) or m.name == bin_name for m in tar.getmembers())
    except tarfile.TarError:
        return False

Try / catch

try:
    install_cbm()
except RuntimeError as e:
    if "binary not found in archive" in str(e):
        logger.warning("asset layout unexpected — installing manual binary")
        manual_install_cbm_from_path("./vendor/codebase-memory-mcp")
    else:
        raise

Prevention

When it happens

Trigger: A platform asset whose top-level binary is named differently (e.g. 'cbm' vs 'codebase-memory-mcp'); a captive portal / misbehaving mirror returning non-tar content that tarfile still opens; a release packaging regression upstream.

Common situations: Pinned versions whose asset layout changed mid-project; running in a container with a transparent HTTP proxy that mangles responses; unusual platform assets (windows zip repackaged as tar.gz).

Related errors


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