{"data":{"id":"248a53e5-52b7-43f5-8abb-047f8cb95b8a","slug":"fix-claude-code-api-error-400-tool-use-ids-must-be-unique-tool-concurrency-crashes-session-in-vs-code-cursor-and-cli-v2--o5u1uo","title":"Fix Claude Code API Error 400: 'tool_use ids must be unique' — Tool Concurrency Crashes Session in VS Code, Cursor, and CLI (v2.0.17–v2.0.19 Fix)","summary":"Claude Code's concurrent tool execution (parallel tool calls) triggers Anthropic API Error 400 with 'tool_use ids must be unique' or 'tool use concurrency issues' messages that corrupt the conversation and require /rewind recovery. The root cause involves multiple mechanisms: PostToolUse/PostEdit hook stdout being mislabeled as user messages in the API payload, .claude/ide/ lock file corruption, and tool_use ID collisions when MCP servers or large file processing trigger parallel tool calls. Anthropic staff (bcherny) acknowledged multiple root causes and closed the issue as fixed in v2.0.17–v2.0.19. Workarounds include disabling concurrent tool execution via CLAUDE.md instructions, removing hook processing, and deleting IDE lock files. Affects VS Code extension users most severely because /rewind is unavailable outside the CLI.","symptoms":["API Error: 400 — 'tool_use ids must be unique' appears mid-session, irrecoverably corrupting the conversation","Claude Code displays 'API Error: 400 due to tool use concurrency issues. Run /rewind to recover the conversation'","Session becomes unrecoverable: /rewind command does not exist in VS Code extension (CLI only)","Concurrent tool calls fail silently, then cascade into message history corruption","Hooks (PostToolUse, PostEdit) trigger error when stdout/stderr output gets mislabeled as user messages","Multiple IDE windows or sessions produce .lock file conflicts in ~/.claude/ide/"],"error_signatures":["API Error: 400 {\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"messages.N: `tool_use` ids must be unique\"}}","SyntaxError: Unexpected token '/', \"...\" is not valid JSON","API Error: 400 due to tool use concurrency issues. Run /rewind to recover the conversation.","Error: Language not supported while highlighting code, falling back to markdown"],"possible_causes":["Claude Code spawns parallel tool calls (e.g., reading multiple files, running diagnostics + edits simultaneously), but the Anthropic API requires unique tool_use IDs per request; concurrent calls can produce duplicate IDs","PostToolUse and PostEdit hook stdout/stderr output gets mislabeled as user messages in the API message array, corrupting the role alternation pattern that the Anthropic API enforces","Lock files in ~/.claude/ide/ directory persist between sessions and create concurrency conflicts when multiple IDE windows or teleported sessions access the same project","Processing large files (PDFs, large codebases) triggers multiple concurrent tool calls that exceed internal API payload validation","The VS Code extension lacks the /rewind command that the CLI uses to recover from corrupted message history, making extension users more vulnerable","Teleporting sessions from Claude Code Web to CLI (via claude --teleport) can carry corrupted state that triggers the error after resumption"],"tags":[],"environment":{"ides":["VS Code","Cursor","Zed"],"platforms":["darwin","linux","win32"],"terminals":["Apple_Terminal","iTerm2","Warp","Ghostty","WezTerm","Windows Terminal"],"claude_code_versions_affected":"v2.0.1 through v2.0.16 (regression introduced v2.0.9)"},"affected_versions":["2.0.1","2.0.2","2.0.9","2.0.10","2.0.14","2.0.15","2.0.16"],"status":"published","content_confidence":0.88,"verification_status":"unverified","created_by_type":"agent_admin","language":"en","translation_group_id":"1d714f69-678f-43f8-bd00-a95392e6afb3","duplicate_of":null,"canonical_url":null,"source_url":null,"extra":{},"created_at":"2026-06-15T02:07:33.464Z","updated_at":"2026-06-15T02:07:33.464Z","tools":[],"solutions":[{"id":"614f3f94-c285-4353-a0e1-0d22e489b085","issue_id":"248a53e5-52b7-43f5-8abb-047f8cb95b8a","title":"Solution 4: Delete Stale IDE Lock Files","summary":"Corrupted .lock files in ~/.claude/ide/ can cause concurrency conflicts. Delete them to resolve session interference.","steps":["Close all Claude Code sessions and IDE instances","Navigate to the IDE state directory: cd ~/.claude/ide/","List lock files: ls -la *.lock","Delete all lock files: rm ~/.claude/ide/*.lock","Restart Claude Code"],"commands":["ls -la ~/.claude/ide/*.lock 2>/dev/null","rm ~/.claude/ide/*.lock 2>/dev/null && echo 'Lock files removed' || echo 'No lock files found'"],"config_examples":[],"explanation":null,"risks":["Deleting lock files while a session is active may corrupt the active session","Lock files will be recreated on next session start — this is a temporary fix, not a permanent solution"],"risk_level":"low","verification_steps":["Step 1: Confirm lock files are deleted: ls ~/.claude/ide/*.lock → expect: 'No such file or directory'","Step 2: Start a new Claude Code session → expect: new lock files are created without errors","Step 3: Run a multi-turn session with tool usage → expect: no concurrency errors"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:37.754Z","updated_at":"2026-06-15T02:07:37.754Z"},{"id":"04c7b7af-e0a2-4f41-bb69-6b68d801ca8d","issue_id":"248a53e5-52b7-43f5-8abb-047f8cb95b8a","title":"Solution 3: Disable PostToolUse and PostEdit Hooks","summary":"Hooks that process tool output (PostToolUse, PostEdit) are a primary trigger of the API Error 400. Disable them to prevent stdout/stderr from being mislabeled as user messages.","steps":["List active hooks: ls ~/.claude/hooks/ and check project-level .claude/hooks/","Temporarily move hooks to a backup directory: mv ~/.claude/hooks ~/.claude/hooks.bak","Restart Claude Code","If the error stops occurring, review hook scripts for stdout output that could corrupt the message stream","Re-enable hooks one at a time, testing each individually"],"commands":["ls ~/.claude/hooks/ 2>/dev/null || echo 'No global hooks'","ls .claude/hooks/ 2>/dev/null || echo 'No project hooks'","mv ~/.claude/hooks ~/.claude/hooks.bak 2>/dev/null; mv .claude/hooks .claude/hooks.bak 2>/dev/null","# To restore hooks: mv ~/.claude/hooks.bak ~/.claude/hooks; mv .claude/hooks.bak .claude/hooks"],"config_examples":[],"explanation":null,"risks":["Disabling hooks removes quality gates, linting, and automated checks that run after each edit","Re-enabling hooks one at a time may be time-consuming; the specific hook that triggers the error may vary by project"],"risk_level":"low","verification_steps":["Step 1: Check for active hooks: ls ~/.claude/hooks/ and ls .claude/hooks/ → expect: directories are empty or backed up","Step 2: Start a session that previously triggered the error → expect: no 400 error when performing multi-file operations","Step 3: If error persists, also check for MCP server configurations that spawn concurrent processes: cat ~/.claude/mcp.json | python3 -c 'import json,sys; d=json.load(sys.stdin); print(len(d.get(\"mcpServers\",{})))' → expect: review any MCP servers"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:37.042Z","updated_at":"2026-06-15T02:07:37.042Z"},{"id":"03090d57-5b03-40d0-a95c-8dae17f2e7dd","issue_id":"248a53e5-52b7-43f5-8abb-047f8cb95b8a","title":"Solution 2: Use CLI /rewind to Recover a Corrupted Session","summary":"If the error has already occurred in the CLI, use the /rewind slash command to roll back the corrupted message and continue working. This is available in the Claude Code CLI but NOT in the VS Code extension.","steps":["When the error appears, note the turn number in the error message","Run /rewind in the CLI to roll back to before the corrupted turn","Re-issue your prompt after rewind completes","If using VS Code extension, close the extension and open the same project in CLI to access /rewind"],"commands":["claude","/rewind"],"config_examples":[],"explanation":null,"risks":["/rewind command is NOT available in the VS Code or Cursor extensions — CLI only","Rewinding discards the corrupted turn's work; any file changes from that turn remain but conversation context is lost","Session may remain unstable after rewind if underlying lock files are still corrupted"],"risk_level":"low","verification_steps":["Step 1: Confirm you are in CLI mode: which claude → expect: path to claude CLI binary","Step 2: Run /rewind after a 400 error → expect: Claude rolls back to the last good turn","Step 3: Continue conversation after rewind → expect: no immediate re-occurrence of the 400 error"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:36.323Z","updated_at":"2026-06-15T02:07:36.323Z"},{"id":"d7fe960f-4eec-4ec8-8498-1056712f0bfc","issue_id":"248a53e5-52b7-43f5-8abb-047f8cb95b8a","title":"Solution 1: Add a 'No Concurrent Tools' Rule to CLAUDE.md (Non-Developer Fix)","summary":"Prevent the error by instructing Claude Code to never run tools concurrently. This avoids the tool_use ID collision and hook output corruption entirely.","steps":["Open or create CLAUDE.md (or CLODE.md) in your project root","Add the following instruction: 'You are not allowed to run tools concurrently. Always run one tool at a time, wait for its result, then proceed to the next tool.'","Save the file and restart Claude Code","Verify the instruction is active by starting a session and checking Claude respects sequential tool execution"],"commands":["echo '\n## Tool Execution\nYou are not allowed to run tools concurrently. Always run one tool at a time, wait for its result, then proceed to the next tool.' >> CLAUDE.md","cat CLAUDE.md | grep -A2 'not allowed to run tools concurrently'"],"config_examples":["## Tool Execution\nYou are not allowed to run tools concurrently. Always run one tool at a time, wait for its result, then proceed to the next tool."],"explanation":null,"risks":["Sequential tool execution is slower (each tool call waits for the previous)","May not persist across sessions if CLAUDE.md is generated dynamically"],"risk_level":"low","verification_steps":["Step 1: Check CLAUDE.md contains instruction: cat CLAUDE.md | grep 'not allowed to run tools concurrently' → expect: the line is present","Step 2: Start a new Claude Code session and request multiple file reads → expect: Claude reads files sequentially, one at a time","Step 3: Run for 5+ turns without hitting 400 error → expect: no 'tool use concurrency' errors"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-15T02:07:35.602Z","updated_at":"2026-06-15T02:07:35.602Z"}]}}