{"record":{"id":"4a4fea2cd2d98c22","repo":"warpdotdev/warp","slug":"claude-p-exited-result-returncode-stderr-resu","errorCode":null,"errorMessage":"claude -p exited {result.returncode}\nstderr: {result.stderr}","messagePattern":"claude -p exited (.+?)\nstderr: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"resources/bundled/skills/create-skill/scripts/improve_description.py","lineNumber":43,"sourceCode":"    cmd = [\"claude\", \"-p\", \"--output-format\", \"text\"]\n    if model:\n        cmd.extend([\"--model\", model])\n\n    # Remove CLAUDECODE env var to allow nesting claude -p inside an\n    # interactive session. The guard is for interactive terminal conflicts;\n    # programmatic subprocess usage is safe. Same pattern as run_eval.py.\n    env = {k: v for k, v in os.environ.items() if k != \"CLAUDECODE\"}\n\n    result = subprocess.run(\n        cmd,\n        input=prompt,\n        capture_output=True,\n        text=True,\n        env=env,\n        timeout=timeout,\n    )\n    if result.returncode != 0:\n        raise RuntimeError(\n            f\"claude -p exited {result.returncode}\\nstderr: {result.stderr}\"\n        )\n    return result.stdout\n\n\ndef improve_description(\n    skill_name: str,\n    skill_content: str,\n    current_description: str,\n    eval_results: dict,\n    history: list[dict],\n    model: str,\n    test_results: dict | None = None,\n    log_dir: Path | None = None,\n    iteration: int | None = None,\n) -> str:\n    \"\"\"Call the agent to improve the description based on eval results.\"\"\"\n    failed_triggers = [","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/warpdotdev/warp/blob/e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc/resources/bundled/skills/create-skill/scripts/improve_description.py#L25-L61","documentation":"improve_description.py drives `claude -p --output-format text` as a subprocess, feeding the prompt on stdin and stripping CLAUDECODE from the environment so the CLI can nest. Whenever the claude process exits non-zero, the script raises RuntimeError embedding the exit code and captured stderr. It is a plain process failure — auth, model access, CLI version, or input rejection — surfaced verbatim.","triggerScenarios":"claude CLI not authenticated or session expired; an invalid --model value forwarded to the CLI; rate-limit/quota rejection mid-loop; a claude binary on PATH old enough to reject the flags used.","commonSituations":"Running the create-skill improve loop in CI or a container where claude was never logged in; specifying a model the account cannot access; flaky network during a long loop; CLI upgrades that change flag semantics.","solutions":["Reproduce manually in the same shell: claude -p 'ping' — read the real error output","Authenticate the CLI (claude login / refresh credentials) — the most common cause","Drop or correct the --model value (try the account's configured default first)","After fixing, re-run the loop — it is idempotent per its history file, and transient rate limits clear on retry"],"exampleFix":"# before\npython scripts/improve_description.py --skill my-skill --model nonexistent-model\n# RuntimeError: claude -p exited 1 ...\n\n# after\npython scripts/improve_description.py --skill my-skill  # use configured default model","handlingStrategy":"retry","validationCode":"import shutil, subprocess\n\nif shutil.which('claude') is None:\n    raise RuntimeError('claude CLI not on PATH')\nsubprocess.run(\n    ['claude', '-p', 'ping'], capture_output=True, text=True, timeout=60\n)  # smoke-test auth before the loop","typeGuard":null,"tryCatchPattern":"import time\n\nfor attempt in range(2):\n    try:\n        return _call_claude(prompt, model)\n    except RuntimeError as e:\n        message = str(e)\n        if attempt == 1 or 'exited' not in message:\n            raise\n        print(f'transient claude failure, retrying: {message}', file=sys.stderr)\n        time.sleep(5)","preventionTips":["Run claude login in CI images that execute this script","Pin a --model the account can access, or omit it","Smoke-test claude -p once before long improve loops","Surface result.stderr in logs — the CLI's real error is always there"],"tags":["cli","subprocess","claude","auth"],"backgroundTag":null,"analyzedSha":"e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc","analyzedAt":"2026-08-16T08:27:25.381Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}