-
-
Notifications
You must be signed in to change notification settings - Fork 80.7k
Bug: skills refresh-state workspaceVersions map retains entries after watcher teardown #77997
Copy link
Copy link
Closed
Labels
P2Normal backlog priority with limited blast radius.Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:crash-loopCrash, hang, restart loop, or process-level availability failure.Crash, hang, restart loop, or process-level availability failure.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.staleMarked as stale due to inactivityMarked as stale due to inactivity
Description
Metadata
Metadata
Assignees
Labels
P2Normal backlog priority with limited blast radius.Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.ClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:crash-loopCrash, hang, restart loop, or process-level availability failure.Crash, hang, restart loop, or process-level availability failure.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.staleMarked as stale due to inactivityMarked as stale due to inactivity
Type
Fields
Priority
None yet
Problem
src/agents/skills/refresh.tsandsrc/agents/skills/refresh-state.tsaccumulate two leaks under the existing call pattern:workspaceVersions: Map<string, number>inrefresh-state.ts:8— populated on every skills file-watch event viabumpSkillsSnapshotVersion({ workspaceDir }). No production removal path. OnlyresetSkillsRefreshStateForTestclears it (test-only).watchers: Map<string, SkillsWatchState>inrefresh.ts:36— populated on everyensureSkillsWatcher(workspaceDir)call. The only production teardown is the rarewatchEnabled=falseconfig path. The hot caller (auto-reply/reply/session-updates.ts:159) callsensureSkillsWatcheron every session turn but never disposes on session end, so each distinct workspaceDir touched by any session adds a chokidar instance that lives for the gateway lifetime.Why it leaks
Drove the unpatched module against 5,000 distinct workspace dirs:
Every entry persists; a fresh untouched workspace correctly reports 0, confirming the persistence is from real Map entries (not a global fallback).
Impact
workspaceVersionsentry, plus full chokidar watcher (FDs + larger overhead) perwatchersentry, scaling with distinct workspace dirs ever touched. Never freed until process restart.watcherscleans up onwatchEnabled=false,workspaceVersionsdoes not — both keyed by workspaceDir but different lifetimes.Tracking PR
Fix in #77998. The PR adds (1)
clearSkillsSnapshotVersionForWorkspacefor safe per-workspace version cleanup, (2)disposeSkillsWatcherfor unified teardown, and (3) opportunistic idle eviction (1h TTL) on everyensureSkillsWatchercall, sowatchers.size ≤ # workspaces touched in the last 1handworkspaceVersions ⊆ watchersas keysets.