microsoft / microsoft/vscode

Agent mode: tool-calling loop silently stalls for minutes after read_file/grep_search results, then resumes on its own

Open
#332,431 1 comment 0 reactions 1 assignee Claimed by @roblourens View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

## Summary

In agent mode the tool-calling loop intermittently stops for minutes after a **file tool** (`read_file`, `grep_search`) has already returned its result. Nothing is in flight during the stall — no model request, no running process, and **not a single line is written to `GitHub Copilot Chat.log`**. There is no error, no timeout message, and no retry. Eventually the loop resumes on its own and the turn finishes normally in seconds.

Because the failure is silent, it is indistinguishable from a slow model, and the usual advice (shorter context, faster model) does not apply — the model is idle the whole time.

## Evidence: every mid-turn stall is waiting on a file tool

Scanning all `GitHub Copilot Chat.log` files and keeping only gaps that occur **while a turn is active** (previous line is a `tools=` progress line or a completed model call within a turn):

| Gap | Last line before the gap |
|---|---|
| 22.4 min | `tools=read_file,read_file` |
| 10.1 min | `tools=grep_search` |
| 8.7 min | `tools=read_file` |
| 6.1 min | `tools=read_file,grep_search` |
| 4.5 min | `tools=grep_search` |
| 1.2 min | `tools=grep_search,read_file` |

Blocking tool distribution across all mid-turn stalls: **`read_file` ×5, `grep_search` ×4**. `run_in_terminal` never appears. The gap lengths (1, 2, 3, 4, 6, 8, 10, 22 min) show no timeout threshold — it looks like a race, not an expiring timer.

## A concrete stall, start to finish

```
22:22:57.456 message 0 returned. finish reason: [tool_calls]
22:22:57.459 ccreq:edce1bb4 | success | | 34946ms | [copilotLanguageModelWrapper]
22:22:57.509 [VoiceProgress] fallback request=... phase=investigating emitted=false tools=grep_search
── 10 minutes 5 seconds, no log output at all ──
22:33:02.253 [AutomaticInstructionsCollector] Core vs extension instructions match (3 entries)
22:33:09.383 Fetched model metadata in 309ms
22:33:15.234 ccreq:a9d7870f | success | | 12464ms
22:33:15.288 [ToolCallingLoop] Stop hook result: shouldContinue=false
```

The UI during the gap showed both tools already completed with results — `Searched for files matching **/.github/workflows/*, 6 matches` and `Read , lines 1 to 40` — followed by an endless `Loading` spinner. When it resumed, the whole turn finished in ~13 seconds.

`terminal.log` for this window is **0 bytes**: no terminal command ran in this session at all, so terminal shell integration cannot be involved in this stall.

## What I measured from outside during a stall

Sampled every 3s for 2 minutes while the spinner was showing:

- **No HTTP request in flight** to the model endpoint. Existing keep-alive sockets simply aged out and closed one by one (3 → 2 → 1).
- Model backend did **zero compute** for the entire window (`nvidia-smi pmon` sm column empty for the backend PID).
- No child process from any tool remained.
- Extension host process was at ~9% CPU — not spinning.
- **Zero new lines** in `GitHub Copilot Chat.log`.

So the extension is not blocked on the model, on I/O, or on a subprocess. The loop simply does not take the next step until, minutes later, it spontaneously does.

Session state on disk confirms the turn is never closed while stalled: no `result`, no `elapsedMs`, no `modelState` is written for that request until it resumes.

## Steps to reproduce

1. Agent mode, a task that makes the agent read/search several files per turn.
2. Let the session run for a while (stalls appeared after the conversation had grown, ~30–120k prompt tokens).
3. Occasionally, after `read_file` / `grep_search` results are rendered, the turn stops with a `Loading` spinner for minutes and then continues by itself.

I could not find a deterministic trigger; it happened 10 times over three days on this machine.

## Environment

- Copilot Chat **0.62.0**, VS Code **1.134.0**
- Debian GNU/Linux 13 (trixie), kernel 6.12.101, bash 5.2.37
- Model: a local OpenAI-compatible endpoint via BYOK (custom endpoint). I verified independently that the endpoint streams correctly (well-formed SSE, correct `finish_reason`, `[DONE]` sent, parallel tool calls with distinct `index`/`id`), sustains ~40 tok/s, and is completely idle during the stalls.

---

## Secondary, separate finding: `run_in_terminal` exit codes

While investigating I found an unrelated problem in the same install, which I originally filed this issue about. Keeping it here rather than opening a second issue; happy to split it out if you prefer.

Across all log directories (308 terminal tool invocations):

| Metric | Count |
|---|---|
| Commands started (`Command rewritten by ...`) | 308 |
| Commands that logged `Finished ... execute strategy` | 219 |
| Commands that never finished | 89 (29%) |
| `Finished ... with exitCode \`undefined\`` | 212 |
| `Finished ... with exitCode \`0\`` | 7 |
| `Shell integration failed to add capabilities within 10 seconds` | 253 |

A real exit code is obtained in 7 of 219 completions (3%). The logs also contradict themselves — the tool reports rich shell integration, and 10 seconds later the same session reports that shell integration never registered:

```
16:43:36.828 trackIdleOnPrompt: Idle scheduler fired, completing (dataEvents=7)
16:43:36.831 RunInTerminalTool: Finished `rich` execute strategy with exitCode `undefined`, result.length `1524`, error `undefined`
16:43:36.832 RunInTerminalTool: shellIntegrationQuality=rich at banner decision time
16:43:46.856 [warning] Shell integration failed to add capabilities within 10 seconds
```

`sequence A after executing` shows OSC 633 A arrives, but the command-finished sequence carrying the exit code evidently does not, so completion falls back to `trackIdleOnPrompt` ("no output for ~1s ⇒ done") — a guess that never fired for 89 invocations. `.bashrc` is stock Debian: no `exec`, no `PROMPT_COMMAND` override, no early return before the interactive check.

Note: this is *not* the cause of the stalls described above — those occur in sessions where no terminal command runs at all.

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.