Bash tool: unrelated stale check.py/pytest output bleeds into tool_result for `for` loops with command substitution

Status Open
Maintainer reply None cached
Activity 0 comments · opened Aug 9, 2026

Description

While running a for loop containing command substitution ($(basename "$f")) inside a single Bash tool call, the tool result repeatedly returned output that appears to come from a completely unrelated scripts/dev/check.py invocation (a project-specific pytest+lint gate script) in the same repo — not from the command that was actually run.

Reproduction

Repo has a PreToolUse hook in .claude/settings.json scoped narrowly to git commit:

"hooks": {
  "PreToolUse": [
    {
      "matcher": "Bash",
      "hooks": [
        {
          "type": "command",
          "if": "Bash(git commit *)",
          "command": "scripts/dev/hooks/pre_commit_gate.sh",
          "timeout": 480
        }
      ]
    }
  ]
}

None of the commands below matched git commit, yet the same stale-looking output appeared repeatedly:

for f in "$TEST_DIR"/.claude/hooks/*.sh; do
  bash -n "$f" && echo "OK: $(basename "$f")" || echo "FAIL: $(basename "$f")"
done

Tool result (observed multiple times, nearly identical text, duration varying by <1s each time):

scripts/dev/check.py falhou:
  → test/test_implementations_new.py::test_endpoint_timeout
  → .../starlette/testclient.py:1: StarletteDeprecationWarning...
  → 28 passed, 19 warnings in 363.xx s (0:06:03)
  2 gate(s) falharam.

What I checked

  • ps aux showed no running pytest/check.py/python3/curl process at the time of failure — ruling out an actually-hung process.
  • Trivial commands (echo, cd ... && pwd, ps aux) run in between always succeeded cleanly.
  • Re-running the exact same for-loop command was non-deterministic: sometimes it failed with this message, sometimes it returned the correct output.
  • Splitting the loop into individual bash -n <file> calls (one Bash tool invocation per file, no loop, no command substitution) never reproduced the issue — 10/10 clean runs.
  • No matching hook in .claude/settings.local.json or global ~/.claude/settings.json that could explain it (checked — no PreToolUse hooks there at all).

Environment

  • Claude Code CLI, macOS (Darwin 25.5.0)
  • Repo has a PreToolUse hook on Bash scoped via an if condition (see above) that runs a ~6 minute pytest suite before git commit

Hypothesis (unconfirmed)

Looks like output/notification cross-talk in the tool-execution layer — possibly a stale or concurrently-running background job's result (from an unrelated check.py invocation, maybe from this same session's hook infra or a race in how if-scoped PreToolUse hook results are attributed to tool calls) getting attached to an unrelated Bash tool_result, more likely to surface when the command itself has more internal steps (loop + subshell command substitution) than a single-line command.

Impact

Not data-destructive, but wastes significant time chasing what looks like a real failure/hang, and erodes trust in tool_result output during a session.

View original on GitHub ↗