microsoft / microsoft/vscode

Browser client tools never return: completions forwarded with source=client-dispatch are never delivered to the pending tool_use

Open
#335,378 0 comments 0 reactions 1 assignee Claimed by @Giuspepe View on GitHub
stale triage-needed
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

# Browser client tools never return: completions forwarded with `source=client-dispatch` are never delivered to the pending `tool_use`

## Summary

Every browser client tool call (`readPage`, `openBrowserPage`, `runPlaywrightCode`, …) hangs indefinitely in the VS Code–based desktop app. The tool itself **succeeds** — the page is read in tens of milliseconds and a completion is forwarded — but the result never reaches the agent's pending `tool_use`. There is no timeout and no rejection, so the turn sits on "Processing" until the user interrupts, which surfaces to the model as `AbortError: interrupt`.

The distinguishing signal is the `source=` tag on the completion. In one session, `agenthost.log` forwarded 44 client tool completions:

| `source=` | count | tools | outcome |
|---|---|---|---|
| `server-envelope` | 41 | Bash, Read, Write, … | all delivered normally |
| `client-dispatch` | 3 | `openBrowserPage`, `runPlaywrightCode`, `readPage` | **all three hung** |

One-to-one, no exceptions. Every browser tool went down the `client-dispatch` path, and every `client-dispatch` completion was lost.

## Where the code lives

All of the identifiers below are in **VS Code core**, not in the agent extension:

```
out/vs/platform/agentHost/node/agentHostMain.js
```

Confirmed by string search across the app bundle vs. the installed extension:

| string | core files | extension files |
|---|---|---|
| `AgentSideEffects` | 1 | 0 |
| `client-dispatch` | 1 | 0 |
| `claudeToolCallRegistry` | 1 | 0 |
| `Forwarding client tool completion` | 1 | 0 |
| `openBrowserPage` / `readPage` | 3 | 0 |
| `withContext` | 2 | 0 |

The browser tools themselves are core-provided, so this is not an extension-side defect.

## Evidence

`agenthost.log` / `window1/renderer.log`, timestamps aligned:

```
20:29:07.751 [info] [AgentHost] Running client tool: openBrowserPage (callId=toolu_01UR…, withContext=true)
20:29:08.923 [info] [AgentSideEffects] Forwarding client tool completion: source=client-dispatch
-> never delivered; user interrupted

20:30:13.116 [info] [AgentHost] Running client tool: runPlaywrightCode (callId=toolu_0177…, withContext=true)
20:30:13.177 [info] [AgentSideEffects] Forwarding client tool completion: source=client-dispatch
-> never delivered; user interrupted

20:36:44.216 [info] [AgentHost] Running client tool: readPage (callId=toolu_0171…, withContext=true)
20:36:44.285 [info] [AgentSideEffects] Forwarding client tool completion: source=client-dispatch
-> never delivered; user interrupted
```

Note the third pair: **69 ms** from dispatch to completion. The page was read successfully. The result was simply never routed back.

Corroborating lines:

```
[claudeToolCallRegistry] turn request_ ended with pending tool_use toolu_; dropping cross-message state
ChatService#cancelCurrentRequestForSession: No pending request was found for session . requestInProgress=false
```

The second one matters: while AgentHost holds an unresolved client tool, `ChatService` believes no request is in progress. So the call is also **uncancellable** — pressing stop reports nothing to cancel.

## Steps to reproduce

1. Open any page in the built-in browser and share it with the agent.
2. Ask the agent to read the page (`readPage`).
3. The call never returns. `agenthost.log` shows the completion forwarded within ~100 ms with `source=client-dispatch`.

## Ruled out by measurement

Each of these was tested and eliminated, so the report isn't a guess about page content:

- **Page size / DOM complexity** — 2288 DOM nodes.
- **Dev server** — HTTP 200 in 0.18 s.
- **Network settling** — `networkidle` reached in 473 ms; zero requests in flight over a 3 s window.
- **Infinite CSS animations** — 5 present (`spin`, `pulse`, an indeterminate progress bar); harmless.
- **`Failed to capture browser view screenshot`** — appears in only 3 of many hangs; two hangs logged no capture error at all. A co-occurring symptom, not the cause.
- **Tab visibility** — the 69 ms successful read happened with the tab *not* visible.
- **Wedged subsystem** — a full window reload did not fix it.

Independently verified the same page with headless Playwright (`playwright-core`): `goto` 314 ms, `load` 89 ms, `networkidle` 473 ms, `screenshot()` 72 ms. The page is entirely healthy.

## Secondary bug: messages sent during a hang never render

A message typed while a tool call is pending **does** reach the model — it is enqueued as steering:

```
[Claude] setPendingMessages … steering=request_
[Claude:] injectSteering: enqueued id=request_ sdkUuid=request_
```

But the UI then subscribes to a changeset resource keyed by that steering request id, which is never created:

```
[ProtocolServer] Request 'subscribe' failed Resource not found: claude://changeset/turn/request_
```

The subscribe fails and the message bubble never draws. The user sees their message vanish and retypes it, while the model has already received it. Four interjections in one session produced exactly four such failures.

## Impact

The browser tooling is unusable in this build, and the two bugs compound badly: the tool hangs, stop does nothing, and the user's attempt to interject appears to fail silently. Users burn turns retyping messages that already arrived.

## Environment

- VS Code `1.136.2` stable, commit `88e44fa0e00b08f7758b4f6d05632e4fd5e4df6f`
- macOS, Darwin 25.6.0 (arm64)
- Agent extension: `anthropic.claude-code` `2.1.266`
- Page under test served from a local dev server over `http://localhost`

Worth noting for triage: GitHub Copilot's browser tooling, in the same window and against the same shared tab, is unaffected — it does not go through the agent host's client-tool dispatch path. So the shared browser view and the page itself are demonstrably fine; only the `client-dispatch` completion route is broken.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.