[BUG] "fg: no job control" hook_non_blocking_error regression on Windows (sync hooks), reappears after #4481
Environment
- Claude CLI version: 2.1.216 (Claude Code)
- Operating System: Windows 11 Pro (build 10.0.26200)
- Terminal: Git Bash (
GNU bash, version 5.3.15(1)-release (x86_64-pc-cygwin)) CLAUDE_CODE_GIT_BASH_PATH:C:\Program Files\Git\bin\bash.exe
Bug Description
fg: no job control reappears as a recurring, non-blocking hook error on Windows, closely matching the symptom originally reported in #4481 (which was closed as fixed in v1.0.77). It reproduces consistently on 2.1.216 for synchronous (non-async) "type": "command" hooks — PreToolUse, non-async PostToolUse, Stop, SessionStart, SessionEnd, Notification, PermissionRequest.
Across a single long session's transcript (~1600 lines), I found:
- 133 occurrences of
stderr: "/usr/bin/bash: line 1: fg: no job control","type": "hook_non_blocking_error", spread acrossPreToolUse:Bash,PreToolUse:Read,PreToolUse:Write,PreToolUse:WebFetch,PreToolUse:WebSearch,PreToolUse:Grep,PreToolUse:Edit,PostToolUse:Read,Stop,SessionStart:resume,SessionStart:compact. - 0 occurrences of this error for hooks marked
"async": truein the same session (e.g. threePostToolUsehooks onEdit|Writethat run auto-backup scripts), despite running many times successfully.
This strongly suggests the synchronous hook-execution path spawns/waits on the configured git-bash process in a way that invokes job control (fg) on a non-interactive shell that never enabled it, while the async path does not.
A related, likely-connected symptom in the same transcript: hooks whose "command" starts with bash.exe directly (e.g. C:/PROGRA~1/Git/bin/bash.exe %USERPROFILE%/.claude/hooks/foo.sh) intermittently failed with Failed with non-blocking status code: /usr/bin/bash: %USERPROFILE%/.claude/hooks/foo.sh: No such file or directory (29 occurrences) — i.e. the Windows-style %USERPROFILE% env-var was not expanded before reaching bash, only for synchronous hooks (the equivalent async: true bash.exe-invoked hooks in the same settings.json never showed this). Both symptoms only affect the synchronous/blocking hook path.
Steps to Reproduce
- On Windows, set
CLAUDE_CODE_GIT_BASH_PATHto a Git for Windowsbash.exe. - Configure any synchronous (no
"async": true) hook of type"command"in~/.claude/settings.json, e.g. underPreToolUse,Stop, orSessionStart. - Trigger the matching event (e.g. run any Bash tool call, or end a turn for
Stop). - Observe
hook_non_blocking_errorwithstderr: "/usr/bin/bash: line 1: fg: no job control"attached to that tool call / turn.
Actual Behavior
The hook's own logic still appears to execute and return the correct result (verified independently by invoking the underlying scripts directly with the same JSON payload — they behave correctly), so this is presented by Claude Code as non-blocking. However it is very noisy: it shows up on nearly every synchronous hook invocation, which across a long session becomes hundreds of spurious error entries in the transcript/UI.
Additional Context
Workaround found for the %USERPROFILE%/"No such file" half of the symptom: switching the hook's "command" fromC:/PROGRA~1/Git/bin/bash.exe %USERPROFILE%/.claude/hooks/foo.sh
toC:/PROGRA~1/Git/bin/bash.exe -c "$HOME/.claude/hooks/foo.sh"
(letting bash itself expand $HOME instead of relying on external %VAR% substitution) eliminated the "No such file" failures. No workaround found for the fg: no job control message itself — it appears to originate from Claude Code's own synchronous hook-invocation wrapper around git-bash, not from anything in the hook script or its command string.
Referencing #4481 since it's the same exact error message and platform, previously closed as fixed for an older 1.0.x version, but reproducing again on 2.1.216 through a different trigger (any synchronous hook, not just "any command" in general).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗