[BUG] Bad substitution when using heredocs with ${var} — runner not using bash
Resolved 💬 3 comments Opened Jan 15, 2026 by PabloZavi Closed Jan 18, 2026
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude Code throws a Bad substitution error when executing commands that include heredocs whose content contains ${var} (e.g. ${i}).
This happens even though the UI indicates the command is executed as Bash(...).
The error originates from the command runner, not from the project code, and often results in:
Bad substitutionshell errors- Unhandled promise rejections
- Subsequent
API Error: 400 due to tool use concurrency issues
Followed in many cases by an unhandled promise rejection and an API 400 error due to tool concurrency issues.
What Should Happen?
The heredoc content should be written verbatim to the file without any shell interpolation or preprocessing by the runner.
Error Messages/Logs
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason: Error: Failed to parse command: Bad substitution: i at ubH (/$bunfs/root/claude:4317:122) at yW (/$bunfs/root/claude:4320:195) at rZ$ (/$bunfs/root/claude:4320:1714) at isReadOnly (/$bunfs/root/claude:2894:1961) ● Bash(cd "/home/pabloz/near-intents-amm-solver/scripts/[v5]transaction-observer" && cat > list-failed-tokens.ts << 'EOF' timeout: 10s atimporty*oas>fs/fromf'fs';…)claude:3072:11288) ⎿ Waiting… at KA1 (/$bunfs/root/claude:3072:11153) at v_A (/$bunfs/root/claude:3072:10730)
Steps to Reproduce
- Ask Claude Code to create a file using a heredoc.
- Include
${i}or${var}inside the heredoc content. - Let Claude execute the generated command.
Example command:
cat > test.ts << 'EOF'
for (const i of items) {
console.log(`Item ${i}`);
}
EOF
### Claude Model
Sonnet (default)
### Is this a regression?
I don't know
### Last Working Version
_No response_
### Claude Code Version
2.1.7 (Claude Code)
### Platform
Anthropic API
### Operating System
Ubuntu/Debian Linux
### Terminal/Shell
WSL (Windows Subsystem for Linux)
### Additional Information
_No response_This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗