# project: Fix agent hanging indefinitely when pulling workspace diagnostics \(\#61176\) · gitcafe/zed

[View on GitCafe](https://git.cafe/gitcafe/zed/commit/c7148c8190d7740d51f6e380f993ba589aaf0751)

Repository: [gitcafe/zed](https://git.cafe/gitcafe/zed)

Visibility: public

Requested revision: c7148c8190d7740d51f6e380f993ba589aaf0751

Requested commit: c7148c8190d7740d51f6e380f993ba589aaf0751

Commit: c7148c8190d7740d51f6e380f993ba589aaf0751

Tree: cc5db23c7b8eb0db5c9e58785f42cbc038e73c61

Author: Lukas Wirth

Committer: GitHub

## Message

```
project: Fix agent hanging indefinitely when pulling workspace diagnostics (#61176)

The agent's diagnostics tool waits on pull_workspace_diagnostics_once,
which enqueues a completion signal into the background workspace
diagnostics refresh loop. When a language server failed to answer
workspace/diagnostic requests, that signal could be stranded, leaving
the agent stuck on 'Check project diagnostics' (reported with logs full
of 'Timeout during workspace diagnostics pull' and requests cancelled
after 120s).

Three hang paths in lsp_workspace_diagnostics_refresh:

1. Timeouts never resolved the completion signal. On
ConnectionResult::Timeout the loop just retried, holding the waiter
through up to 50 attempts x 120s each (~100 minutes) before the sender
was finally dropped.

2. Waiters could queue behind an already-hanging request. The refresh
channel has capacity 1; if the loop was mid-retry (e.g. the initial pull
at server startup was timing out), a newly enqueued waiter sat
unreceived until the entire retry cycle ended.

3. The request timeout was permanently disabled after the first partial
result. The timer raced progress_rx.recv() once and became pending()
forever if progress won, so a server that streamed one chunk and then
stalled hung the request indefinitely.

Fixes:

- On timeout, release all pending waiters (including ones that queued
mid-flight) with refreshed = false, so callers fall back to cached
diagnostics after at most one timeout period while the background loop
keeps retrying.

- Carry waiters as a Vec and absorb refresh requests queued during
backoff/in-flight requests into the current attempt instead of
serializing them behind it.

- Restart the timeout whenever a partial result arrives, turning it into
an inactivity timeout: streaming servers get unlimited total time while
they keep making progress, but a stalled stream now times out instead of
hanging forever.

Adds a regression test with a fake server that never answers workspace
diagnostic pulls, verifying the waiter resolves after the timeout; it
fails with 'Parking forbidden' (infinite hang) without the fix.

Closes FR-124

Release Notes:

- Fixed agents hanging indefinitely if an LSP server never responds to
diagnostics requests
```

## Parents

- [94e59ce2f83a3aaaf80efa2fd2c6a033994b0b34](https://git.cafe/gitcafe/zed/commit/94e59ce2f83a3aaaf80efa2fd2c6a033994b0b34?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zed/tree/c7148c8190d7740d51f6e380f993ba589aaf0751?format=markdown)
