# fix(agent-core): macOS file descriptor exhaustion in workspace scanner
Note: This issue follows the Contributing Guidelines. Per the guidelines: "Discuss first — open an issue before coding. PRs without prior discussion may be closed without review." This issue is opened to discuss the bug and proposed fix before submitting a PR.
If approved, the intended PR would be titled: fix(agent-core): use fsevents on macOS to prevent file descriptor exhaustion
and includes a changeset (.changeset/fsevents-macos-workspace-watcher.md, bump level: patch for @moonshot-ai/kimi-code — agent-core-v2 is an internal package whose changes ship inside the CLI bundle).
Bug Description
When working with a large workspace on macOS, Kimi Code's web UI (kimi web) eventually loses the ability to spawn Bash and other tools. The workspace scanner crashes or hangs, and the tool registry desyncs from the session.
Environment
Known from the Kimi Code GitHub repository (MoonshotAI/kimi-code):
Your local environment (please fill in):
| Component |
Your Value |
How to check |
| OS |
Darwin 25.5.0 |
uname -s -r |
| Architecture |
arm64 |
uname -m |
| Node.js |
v26.5.0 |
node --version |
| Kimi Code |
0.31.1 |
kimi --version |
| Chokidar (resolved) |
4.0.3 |
grep chokidar pnpm-lock.yaml |
| Shell |
/bin/bash |
echo $SHELL |
| Workspace |
187 files |
`find . -type f |
| Git repo? |
no |
git rev-parse --git-dir... |
| ulimit -n |
1048575 |
ulimit -n |
| kern.maxfilesperproc |
61440 |
sysctl -n kern.maxfilesperproc |
Steps to Reproduce
- Open a large workspace on macOS (e.g., a monorepo with >15,000 files including
node_modules).
- Run
kimi web.
- Wait for the workspace scanner / file-mention index to refresh (observed every ~30s).
- After several refresh cycles, attempt to use the Bash tool in the web UI.
- Expected: Bash tool spawns normally.
Actual: Bash tool is unavailable; the web UI shows "model is not configured" or tools silently fail.
Observed Behavior
kimi web starts normally.
- After some time, the web UI becomes unresponsive or loses tool access.
lsof -p $(pgrep -f kap-server) shows thousands of open file descriptors (one per watched file/directory).
- Restarting
kimi web temporarily fixes the issue until the scanner re-runs.
The directory in question has some 501485 files in it. This is a mono-repo comprised of some 20 submodules. The issue was found to be with a bug in the chokidar library on Mac OSX that did not exist in chokidar 3.x. chokidar 4.x/5.x both have the issue. Kimi Code was used to discover the problem and create a patch. The patch is running locally and fixes the issue. Kimi ran a build on a docker image for running a Linux build and found that to pass. A windows build was not attempted as I do not have access to Windows machine.
While one could argue a large repo is not ideal, I have worked on Android Automotive with many more files, and used VS Code to search and process the entire android codebase. So, it would be useful it Kimi would work.
Root Cause Analysis
Kimi Code's FsWatcherService (in packages/agent-core-v2) uses chokidar v4 (^4.0.3). Chokidar v4 removed fsevents and switched to individual node:fs.watch() calls — one per file and one per directory. On macOS, each fs.watch() opens a kqueue descriptor. Workspaces with tens of thousands of files exhaust the per-process file-descriptor limit (ulimit -n / kern.maxfilesperproc), causing:
- The workspace scanner to fail mid-cycle.
- File handles to leak because the watcher does not clean up properly on failure.
- The
Workspace scope handler to desync, which drops the tool registry (Bash, Edit, etc.) from the session.
This is a known upstream regression in chokidar v4/v5:
kimi-diagnostic-20260802-140214.tar.gz
kimi-code-fsevents-macos-fix.patch
# fix(agent-core): macOS file descriptor exhaustion in workspace scanner
Bug Description
When working with a large workspace on macOS, Kimi Code's web UI (
kimi web) eventually loses the ability to spawn Bash and other tools. The workspace scanner crashes or hangs, and the tool registry desyncs from the session.Environment
Known from the Kimi Code GitHub repository (
MoonshotAI/kimi-code):0.31.1(latest release, 2026-07-31)>= 24.15.0(required)package.jsonengines^4.0.3(dependency inagent-core-v2)packages/agent-core-v2/package.jsonpnpm@10.33.0package.jsonpackageManagerpackage.jsonwithapps/,packages/workspacesYour local environment (please fill in):
uname -s -runame -mnode --versionkimi --versiongrep chokidar pnpm-lock.yamlecho $SHELLgit rev-parse --git-dir...ulimit -nsysctl -n kern.maxfilesperprocSteps to Reproduce
node_modules).kimi web.Actual: Bash tool is unavailable; the web UI shows "model is not configured" or tools silently fail.
Observed Behavior
kimi webstarts normally.lsof -p $(pgrep -f kap-server)shows thousands of open file descriptors (one per watched file/directory).kimi webtemporarily fixes the issue until the scanner re-runs.The directory in question has some 501485 files in it. This is a mono-repo comprised of some 20 submodules. The issue was found to be with a bug in the chokidar library on Mac OSX that did not exist in chokidar 3.x. chokidar 4.x/5.x both have the issue. Kimi Code was used to discover the problem and create a patch. The patch is running locally and fixes the issue. Kimi ran a build on a docker image for running a Linux build and found that to pass. A windows build was not attempted as I do not have access to Windows machine.
While one could argue a large repo is not ideal, I have worked on Android Automotive with many more files, and used VS Code to search and process the entire android codebase. So, it would be useful it Kimi would work.
Root Cause Analysis
Kimi Code's
FsWatcherService(inpackages/agent-core-v2) useschokidarv4 (^4.0.3). Chokidar v4 removedfseventsand switched to individualnode:fs.watch()calls — one per file and one per directory. On macOS, eachfs.watch()opens akqueuedescriptor. Workspaces with tens of thousands of files exhaust the per-process file-descriptor limit (ulimit -n/kern.maxfilesperproc), causing:Workspacescope handler to desync, which drops the tool registry (Bash, Edit, etc.) from the session.This is a known upstream regression in chokidar v4/v5:
EMFILE: too many open files, watchEBADFwhen watching many files on macOSchild_process.fork()fails due to descriptor exhaustionkimi-diagnostic-20260802-140214.tar.gz
kimi-code-fsevents-macos-fix.patch