Claude initiates a tool call — web search, code execution, MCP server, custom function — and the spinner just stays spinning. Five minutes later it is still pending. There is no error message, no timeout, just a hung state. Refreshing the page often returns to the same hung state. The root cause is almost always either a missing tool_result response (the server never replied), the response was returned in the wrong format, or a slow long-running tool that exceeds Claude’s UI timeout window. Once you know which, the fix is straightforward.
Common causes
Ordered by hit rate, highest first.
1. Tool server never returned a result
For API integrations and MCP servers, Claude waits for a tool_result content block. If the server crashed, took longer than its own timeout, or never sent the response, Claude UI shows the call as pending forever.
How to judge: Check the tool server logs for a request matching the timestamp. No log entry at all = request never landed. Log entry but no response = server crashed mid-call.
2. Tool result returned but with wrong content type / shape
The Anthropic API expects tool_result blocks with tool_use_id and content. If the integration returned a plain string, a text block instead of tool_result, or omitted tool_use_id, Claude does not match it back and the call stays pending in UI.
How to judge: Inspect the raw API response. The block should look like { "type": "tool_result", "tool_use_id": "toolu_...", "content": "..." }.
3. Web search or code execution exceeded the per-call timeout
Built-in tools (web search, code interpreter) have per-call timeouts. A query that returns no result in time stalls without erroring out.
How to judge: Wait 90 seconds. If still pending, it has likely exceeded the timeout silently. Refresh the conversation; the call usually disappears or shows an error.
4. MCP server connection dropped mid-call
If you are using MCP-connected tools (filesystem, GitHub, custom servers), a connection drop during the call leaves the UI in flight. The new connection cannot resume the in-flight call.
How to judge: Settings → Connectors → status of each MCP server. If any show “disconnected” or “reconnecting,” that is likely the one.
5. Browser tab was backgrounded and connection got suspended
Chrome and Safari suspend long-lived connections in background tabs. If you switched away mid-tool-call, the streaming response may have been killed.
How to judge: Bring the tab to foreground, wait 10 seconds, see if it recovers. If not, refresh.
6. Multiple concurrent tool calls confused the UI state
When Claude fires several tool calls in parallel and one returns out of order, the UI sometimes mis-tracks which is still pending vs already finished.
How to judge: Look at the chain of tool calls. If the latest call shows results but an earlier one is still pending, it is a UI tracking glitch.
Before you start
- Note whether the tool is built-in (web search, code execution), an MCP connector, or a custom API integration; the fix lane differs.
- Have the tool server logs available if it is a custom or MCP tool.
- Decide whether you want to cancel and retry, or wait it out — cancelling loses partial progress.
Information to collect
- Which tool was called (name, integration, or built-in label).
- Approximate timestamp of the call (for log correlation).
- Tab state: foreground or background, browser, OS.
- Whether other tool calls in the same conversation worked normally.
- For API integrations: the raw HTTP response your server returned.
- For MCP: connector status in Settings.
Step-by-step fix
Step 1: Refresh the conversation page
About 30% of pending calls clear on refresh. The connection reconnects and Claude re-reads the conversation state. If the call was in fact completed server-side, it will show its result; if it really hung, it will reappear as pending or as an error.
Step 2: Wait the full timeout window
For built-in tools the timeout is typically 60-120 seconds. Set a timer and wait. If the call eventually shows an error or “no result,” that is the right outcome — retry the prompt with a smaller scope.
Step 3: Check status page and connector status
Open status.anthropic.com in a new tab. If web search or code execution is degraded, every call to those tools will hang. Also: Settings → Connectors → confirm none show disconnected.
Step 4: For custom integrations, inspect the server response
The Anthropic API needs a tool_result block to close the loop:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01ABC...",
"content": "the result string or structured content"
}
]
}
If your server returned a plain string or omitted tool_use_id, Claude has no way to match it. Fix the response shape and the conversation will move forward.
Step 5: For MCP, reconnect the server
If a connector shows “disconnected”: Settings → Connectors → click the connector → Reconnect. Then retry the prompt in a new turn (not the hung turn). Reconnecting will not retroactively complete the stuck call.
Step 6: Cancel and retry with a narrower scope
If wait, refresh, and reconnect all failed, cancel the hung call:
Stop the current tool call. Try again, but instead of searching
the entire repository, only search the apps/web/src/billing/ directory.
A smaller scope usually completes within timeout.
Step 7: For long-running tools, switch to background execution
For tools that take more than 60 seconds (large data jobs, slow APIs), redesign the tool to return a job ID immediately and let Claude poll:
1. Tool call A: starts the job, returns { "job_id": "abc123" }
2. Tool call B: checks status by job_id, returns done or pending
This avoids hitting the UI timeout altogether.
Verify
- Repeat the same prompt in a fresh conversation. If it now completes quickly, the fix worked.
- For custom integrations, send a
tool_resulttest message with the sametool_use_idshape and confirm Claude accepts it. - For MCP, run a simple tool call (list files, get user) and confirm it returns quickly.
- Leave the tab in foreground during the retry to rule out browser suspension.
Long-term prevention
- For custom tool servers, set internal timeouts shorter than Claude’s UI timeout (45s) and always return either a result or an error within that window.
- For MCP servers, add health checks and auto-reconnect on transient failures.
- For built-in tools, keep prompts scoped: “search recent posts about X” instead of “search the entire web for everything about X.”
- Keep DevTools Network open during tool-heavy conversations to catch shape mismatches early.
- Document the expected
tool_resultshape in your tool-server README so future integrations do not regress.
Common pitfalls
- Refreshing the page 5 times in a row. Once is enough; more does not help.
- Returning the tool result as plain text instead of a
tool_resultblock. Easy to miss in custom integrations. - Forgetting that
tool_use_idis per-call, not per-tool. Each call has a fresh ID. - Letting a custom tool run 5+ minutes without returning anything. Claude UI will not wait.
- Treating an MCP “connected” badge as proof the server is healthy — make an actual call to verify.
FAQ
- How long is Claude’s tool-call timeout? Built-in tools time out around 60-120s. Custom integrations depend on your own server; the API itself does not enforce a strict cap, but the Claude.ai UI does.
- Can I cancel a pending tool call? Click the stop button on the spinner. If that does nothing, refresh the page; the call should clear.
- Will the call eventually complete on its own? If the server eventually replies with a valid
tool_result, yes. If not, no — refresh. - Does this happen on the API too? On the raw API you control the loop, so you would see the request hanging in your own client, not in Claude UI. The diagnosis is similar.
- Is this a Claude bug? Sometimes — the UI does occasionally lose track of call state. But more often it is a downstream tool that did not respond properly.
Related
- Claude Skills Not Firing When Expected
- Claude Chrome connector issue
- Claude connector no permission
- Claude file upload stuck on processing
- Claude beginner guide
Tags: #Claude #Troubleshooting #Tools