agentHost: a transient git failure can permanently freeze a folder-isolated session's project
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
Found while reviewing the two competing fixes for #329880 (#329925 and #329932). It is out of scope for both, but the same failure mode, so filing it separately rather than losing it when one of them merges.
## What happens
`resolveGitProject` (`src/vs/platform/agentHost/node/copilot/copilotGitProject.ts`) resolves a session's project and, when the primary worktree cannot be resolved, **falls back to the checkout root**. `CopilotAgent` then persists that fallback and marks it resolved (`node/copilot/copilotAgent.ts`, around the `projectResolved` write).
The fallback is indistinguishable from a real answer, because `getWorktreeRoots` swallows every git failure into `[]` — a repository that is genuinely not a worktree, a git that timed out, an index-lock contention, and an `EAGAIN` under load all look identical.
So a *momentary* condition — a network volume briefly unavailable, a slow FUSE mount, git timing out under load — can be persisted as a settled answer.
## Why it is durable
Unlike worktree-isolated sessions, **folder-isolated sessions have no worktree metadata migration to correct it later**. Nothing re-derives the value, so a transient blip becomes a permanently mis-grouped session in the Agents window, with no user affordance to repair it short of editing the session database.
## Reproduction
A fake git service that fails once and then recovers returns the linked checkout root **both** times, with only one git call — the persisted fallback is never revisited.
## Suggested direction
Return a typed `{ root, confirmed }` from the resolution rather than a bare `URI`, and never persist an unconfirmed fallback as resolved. An unconfirmed project should stay unpersisted so a later attempt can settle it.
This is the same shape as two bugs already fixed in #329932: an unconfirmed value must never be certified, and "git failed" must not be collapsed into "git answered no". Worth applying the same rule here.
## Notes
- Affects both #329925 and #329932 equally; neither introduces it and neither fixes it.
- Related hardening already landed in #329932: `canonicalizeExistingPath` now reports absence only for `ENOENT`/`ENOTDIR` so that an unreadable or briefly-unavailable path is not mistaken for a deleted one.
Contributor guide
Assessment
This issue has not been assessed yet.