Skip to content

Copilot CLI never prunes ~/.copilot/session-state, causing EMFILE / file-descriptor exhaustion (crashes VS Code Copilot Chat) #3892

Description

@markjbrown

Summary

The Copilot CLI creates a ~/.copilot/session-state/<guid>/ folder for every session — including background automations, heartbeats, and memory-consolidation runs — and never prunes them. On a heavily-used machine these accumulate into the thousands. A Copilot component then bulk-opens session-state/*/workspace.yaml, exhausting the process's file-descriptor table (libuv's ~8189 limit on Windows) and throwing EMFILE: too many open files. In VS Code this makes Copilot Chat hang on "working" and crash after a few turns.

This is the root cause behind microsoft/vscode#313799 — that's where it manifests, but the fix belongs here.

Evidence (Windows, measured with Sysinternals handle.exe)

  • ~/.copilot/session-state contained 10,313 workspace.yaml files, accumulated since 2026-02-18, never pruned.
  • The Copilot node.mojom.NodeService utility process peaked at ~8,788 open handles — right at the libuv fd ceiling — then dropped back to ~580 after the burst (which is why point-in-time snapshots look normal).
  • In a single mid-spike handle dump, 3,256 of 3,352 (97%) File-handle paths were session-state\...\workspace.yaml.
  • Reducing the folder count to ~67 immediately resolved the EMFILE crashes.

Two underlying issues

  1. No retention/cleanup (primary): session-state folders grow unbounded — no age or count cap, no garbage collection.
  2. Unbounded fan-out open: the code that reads workspace.yaml across sessions opens them without bounding concurrent file descriptors or closing promptly, so a large directory exhausts the fd table instead of degrading gracefully.

Suggested fixes

  • Add automatic retention (e.g., prune session-state older than N days, or cap to the M most-recent) on CLI startup and/or via a background task.
  • Bound concurrency and ensure prompt handle closure when enumerating session metadata.
  • Optionally consolidate session metadata into a single index/DB rather than one folder + file per session.

Workaround

Periodically prune ~/.copilot/session-state (e.g., a scheduled task that deletes folders older than ~14 days).

Environment

Windows; GitHub Copilot CLI + VS Code Copilot Chat (stable).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:sessionsSession management, resume, history, session picker, and session state

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions