{"record":{"id":"8e7dde22cc06aaa3","repo":"headroomlabs-ai/headroom","slug":"join-cmd-did-not-respond-within-hard-cap","errorCode":null,"errorMessage":"`{' '.join(cmd)}` did not respond within {hard_cap}s. Check network connectivity, raise HEADROOM_LEARN_CLI_TIMEOUT_SECS, or try a different backend with --model <litellm-model-name>.","messagePattern":"`(.+?)` did not respond within (.+?)s\\. Check network connectivity, raise HEADROOM_LEARN_CLI_TIMEOUT_SECS, or try a different backend with --model <litellm-model-name>\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"headroom/learn/analyzer.py","lineNumber":607,"sourceCode":"            timeout=hard_cap,\n        )\n    except FileNotFoundError:\n        shim_cmd = _resolve_windows_cli_shim(cmd)\n        if shim_cmd is None:\n            raise RuntimeError(\n                f\"`{cmd[0]}` not found in PATH. Install it or use a different backend \"\n                \"with --model <litellm-model-name>.\"\n            ) from None\n        cmd = shim_cmd\n        try:\n            result = run(cmd, input=prompt, capture_output=True, text=True, timeout=hard_cap)\n        except FileNotFoundError:\n            raise RuntimeError(\n                f\"`{cmd[0]}` not found in PATH. Install it or use a different backend \"\n                \"with --model <litellm-model-name>.\"\n            ) from None\n    except subprocess.TimeoutExpired:\n        raise RuntimeError(\n            f\"`{' '.join(cmd)}` did not respond within {hard_cap}s. \"\n            \"Check network connectivity, raise HEADROOM_LEARN_CLI_TIMEOUT_SECS, \"\n            \"or try a different backend with --model <litellm-model-name>.\"\n        ) from None\n\n    if result.returncode != 0:\n        stderr_snippet = (result.stderr or \"\")[:_MAX_SNIPPET_LEN]\n        raise RuntimeError(\n            f\"`{' '.join(cmd)}` failed (exit {result.returncode}):\\n{stderr_snippet}\"\n        )\n\n    # Log stderr warnings even on success (auth refreshes, deprecation notices).\n    if result.stderr and result.stderr.strip():\n        logger.debug(\"CLI stderr (exit 0): %s\", result.stderr[:_MAX_SNIPPET_LEN])\n\n    try:\n        return _strip_fenced_json(result.stdout)\n    except json.JSONDecodeError as exc:","sourceCodeStart":589,"sourceCodeEnd":625,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/learn/analyzer.py#L589-L625","documentation":"Raised when the CLI subprocess exceeded the hard cap: subprocess.run(..., timeout=hard_cap) raised subprocess.TimeoutExpired and the process was killed. hard_cap defaults to _CLI_TIMEOUT=300s and is overridable via HEADROOM_LEARN_CLI_TIMEOUT_SECS (resolved by _resolve_timeout_secs). The message suggests connectivity checks, raising the cap, or switching backends.","triggerScenarios":"`headroom learn` with a CLI backend (claude/gemini/codex) whose analysis run takes longer than the cap — large session digests, slow model responses, network stalls — and HEADROOM_LEARN_CLI_TIMEOUT_SECS unset or set too low.","commonSituations":"Huge conversation digests sent for analysis; corporate proxies/rate limits slowing the CLI; the default 300s being lowered by a copied env var; free-tier CLI backends queuing requests.","solutions":["Raise the cap: export HEADROOM_LEARN_CLI_TIMEOUT_SECS=900 (or higher for big digests)","Check the CLI manually with the same prompt to see whether it's genuinely slow or hung (network/auth issue)","Switch to a faster/healthier backend: use the claude-cli streaming path (which has an idle-based cap instead) or an API model via --model <litellm-model-name>"],"exampleFix":"# before\nheadroom learn  # CLI killed at 300s default\n\n# after\nexport HEADROOM_LEARN_CLI_TIMEOUT_SECS=900\nheadroom learn","handlingStrategy":"retry","validationCode":"import os\ncap = int(os.environ.get('HEADROOM_LEARN_CLI_TIMEOUT_SECS', 300))\nif cap < 600 and my_digest_is_large:\n    os.environ['HEADROOM_LEARN_CLI_TIMEOUT_SECS'] = '900'","typeGuard":null,"tryCatchPattern":"for attempt in range(2):\n    try:\n        return run_learn()\n    except RuntimeError as e:\n        if 'did not respond within' in str(e) and attempt == 0:\n            os.environ['HEADROOM_LEARN_CLI_TIMEOUT_SECS'] = '900'\n            continue\n        raise","preventionTips":["Scale HEADROOM_LEARN_CLI_TIMEOUT_SECS with digest size before running","Smoke-test the CLI's latency with a small prompt to detect network issues early","Prefer the claude streaming backend (idle-based timeout) when total runtime is unpredictable"],"tags":["timeout","cli","subprocess","configuration"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}