{"record":{"id":"0b8abbcfc2b74b26","repo":"shareAI-lab/learn-claude-code","slug":"only-bash-can-run-in-the-background","errorCode":null,"errorMessage":"only bash can run in the background","messagePattern":"only bash can run in the background","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s15_integrated_harness/code.py","lineNumber":2108,"sourceCode":"\ndef should_run_background(tool_name: str, tool_input: dict) -> bool:\n    return (\n        tool_name == \"bash\"\n        and tool_input.get(\"run_in_background\") is True\n    )\n\n\ndef start_background_task(block, handlers: dict) -> str:\n    global _bg_counter\n    _bg_counter += 1\n    bg_id = f\"bg_{_bg_counter:04d}\"\n    command = block.input.get(\"command\", block.name)\n    cwd, cwd_error = _agent_cwd()\n\n    def worker():\n        try:\n            if block.name != \"bash\":\n                raise ValueError(\"only bash can run in the background\")\n            if cwd_error:\n                raise ValueError(cwd_error.removeprefix(\"Error: \"))\n            output, exit_code = _run_bash_process(\n                str(block.input[\"command\"]), cwd)\n            result = _format_bash_result(output, exit_code)\n            status = \"completed\" if exit_code == 0 else \"failed\"\n        except Exception as exc:\n            result = f\"Error: {type(exc).__name__}: {exc}\"\n            status = \"failed\"\n        trigger_hooks(\"PostToolUse\", block, result)\n        with background_lock:\n            background_tasks[bg_id][\"status\"] = status\n            background_results[bg_id] = str(result)\n\n    with background_lock:\n        background_tasks[bg_id] = {\n            \"tool_use_id\": block.id,\n            \"command\": command,","sourceCodeStart":2090,"sourceCodeEnd":2126,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s15_integrated_harness/code.py#L2090-L2126","documentation":"start_background_task() executes a tool block in a worker thread, but only the 'bash' tool is eligible: any other tool name (read, edit, mcp__*, ...) raises this inside the worker, so the background entry is marked failed with 'Error: ValueError: only bash can run in the background'. Long-running work is exclusively shell commands by design.","triggerScenarios":"Requesting background execution for a non-bash block — e.g. marking a read_file or MCP tool call as background/async; a scheduler that routes every slow tool through start_background_task; block.name mutated between validation and dispatch.","commonSituations":"Agents trying to background a slow MCP fetch; wrappers that set a background flag generically on all tool calls; version change where the flag started applying to more tools.","solutions":["Run only bash commands in the background; run other tools synchronously.","For slow non-bash operations, wrap them in a shell command (e.g. curl) if policy permits.","Gate the background option on block.name == 'bash' in the caller before invoking start_background_task."],"exampleFix":"// before\nstart_background_task(read_block, handlers)  // block.name == 'read'\n\n// after\nif block.name == \"bash\":\n    start_background_task(block, handlers)\nelse:\n    run_sync(block, handlers)","handlingStrategy":"validation","validationCode":"def can_background(block) -> bool:\n    return block.name == \"bash\"","typeGuard":"def is_bash_block(block) -> bool:\n    return getattr(block, \"name\", None) == \"bash\"","tryCatchPattern":null,"preventionTips":["Only request background execution for bash blocks.","Gate the background flag on tool name in your wrapper.","For slow non-bash ops, run synchronously or wrap in a shell command."],"tags":["background","tools","bash","validation"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}