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

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions