claude-code - 💡(How to fix) Fix Chokidar file watchers with unlimited depth exhaust Windows Non-Paged Pool (NPP) kernel memory [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#48648Fetched 2026-04-16 06:54:45
View on GitHub
Comments
1
Participants
1
Timeline
7
Reactions
0
Author
Participants
Timeline (top)
labeled ×4cross-referenced ×2commented ×1

Claude Code creates 8 chokidar file watchers, 4 with unlimited directory depth. On Windows, each watched directory creates a kernel ReadDirectoryChangesW handle consuming Non-Paged Pool (NPP) memory. For projects with deep directory trees (e.g., node_modules/), this can allocate tens of thousands of kernel handles, exhausting NPP.

Root Cause

The .bun section of claude.exe v2.1.109 contains 8 Aa.watch() (chokidar) call sites:

WatcherdepthPurpose
Settings files watcher0Config file changes
FileChanged (project files)unlimitedSource code monitoring
Keybindings watcherunlimitedKeybinding file changes
Skill/command directories2Plugin directory changes
(4 duplicates in bundle)(same patterns repeated)

The 4 unlimited-depth watchers are the concern. On Windows, chokidar falls back to ReadDirectoryChangesW which creates one kernel handle per watched subdirectory. A typical Node.js project:

  • node_modules/: 5,000-20,000 subdirectories
  • .git/objects/: hundreds of pack directories
  • dist/, build/, target/: build output trees

With 4 unlimited-depth watchers, a single project could create 20,000-80,000 kernel directory handles. Each handle consumes kernel Non-Paged Pool memory (~1-4 KB per handle for the NTFS FCB + associated structures).

Estimated NPP per project: 20,000 handles × 2 KB avg = ~40 MB NPP per project per claude.exe process.

With 3 concurrent claude.exe processes (main + subagents), each watching the same project: ~120 MB NPP just from watchers.

Code Example

// Observed pattern in bundle
Aa.watch(L, {
  persistent: true,
  ignoreInitial: true,
  awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 200 },
  ignorePermissionErrors: true
  // no 'ignored' for node_modules, .git, dist, build, target
});
RAW_BUFFERClick to expand / collapse

Summary

Claude Code creates 8 chokidar file watchers, 4 with unlimited directory depth. On Windows, each watched directory creates a kernel ReadDirectoryChangesW handle consuming Non-Paged Pool (NPP) memory. For projects with deep directory trees (e.g., node_modules/), this can allocate tens of thousands of kernel handles, exhausting NPP.

Analysis

The .bun section of claude.exe v2.1.109 contains 8 Aa.watch() (chokidar) call sites:

WatcherdepthPurpose
Settings files watcher0Config file changes
FileChanged (project files)unlimitedSource code monitoring
Keybindings watcherunlimitedKeybinding file changes
Skill/command directories2Plugin directory changes
(4 duplicates in bundle)(same patterns repeated)

The 4 unlimited-depth watchers are the concern. On Windows, chokidar falls back to ReadDirectoryChangesW which creates one kernel handle per watched subdirectory. A typical Node.js project:

  • node_modules/: 5,000-20,000 subdirectories
  • .git/objects/: hundreds of pack directories
  • dist/, build/, target/: build output trees

With 4 unlimited-depth watchers, a single project could create 20,000-80,000 kernel directory handles. Each handle consumes kernel Non-Paged Pool memory (~1-4 KB per handle for the NTFS FCB + associated structures).

Estimated NPP per project: 20,000 handles × 2 KB avg = ~40 MB NPP per project per claude.exe process.

With 3 concurrent claude.exe processes (main + subagents), each watching the same project: ~120 MB NPP just from watchers.

Relationship to NtFC Pool Tag

Issues #45889 and #45921 identify pool tag NtFC (NTFS File Control Block) as the dominant NPP consumer. ReadDirectoryChangesW triggers NTFS FCB allocation for each watched directory. The watchers create a sustained baseline of FCB allocations that compound with other file I/O patterns.

Additional concern: no depth exclusions

The chokidar call sites do not appear to use ignored patterns for common large directories:

// Observed pattern in bundle
Aa.watch(L, {
  persistent: true,
  ignoreInitial: true,
  awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 200 },
  ignorePermissionErrors: true
  // no 'ignored' for node_modules, .git, dist, build, target
});

Suggested Fix

  1. Set explicit depth limits on project file watchers (depth 3-5 covers most source trees)
  2. Exclude common large directories: node_modules, .git, dist, build, target, vendor, __pycache__, .next, .nuxt
  3. Consider polling mode on Windows for deep directories (usePolling: true with reasonable interval)
  4. Share watchers across processes — subagents shouldn't each create their own project watchers

Environment

  • claude.exe v2.1.109 (Bun binary), Windows 11 Pro 10.0.26200
  • Analysis method: PE section extraction + chokidar call site enumeration

Related Issues

  • #45889 (NtFC pool tag NPP leak — same root cause, different reporter)
  • #45921 (VM temp file NPP leak — different vector, same pool tag)
  • #43548 (closed — extreme Other I/O rate causing NPP exhaustion)
  • #42169 (overall resource exhaustion report including NPP)

extent analysis

TL;DR

Set explicit depth limits on project file watchers and exclude common large directories to mitigate Non-Paged Pool memory exhaustion.

Guidance

  • Review the chokidar call sites in claude.exe and set explicit depth limits (e.g., 3-5) for project file watchers to reduce the number of kernel handles created.
  • Add ignored patterns for common large directories such as node_modules, .git, dist, build, and target to prevent unnecessary watching.
  • Consider enabling polling mode on Windows for deep directories by setting usePolling: true with a reasonable interval to reduce the load on the kernel.
  • Investigate sharing watchers across processes to avoid duplicate watchers and further reduce kernel handle creation.

Example

Aa.watch(L, {
  persistent: true,
  ignoreInitial: true,
  awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 200 },
  ignorePermissionErrors: true,
  ignored: ['node_modules', '.git', 'dist', 'build', 'target'],
  depth: 3 // set explicit depth limit
});

Notes

The suggested fixes aim to reduce the number of kernel handles created by chokidar, which should help mitigate Non-Paged Pool memory exhaustion. However, the optimal depth limit and ignored patterns may vary depending on the specific project structure and requirements.

Recommendation

Apply the suggested fixes, starting with setting explicit depth limits and excluding common large directories, to reduce the risk of Non-Paged Pool memory exhaustion.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Chokidar file watchers with unlimited depth exhaust Windows Non-Paged Pool (NPP) kernel memory [1 comments, 1 participants]