#14023: fix: filter skills watcher to relevant file types to prevent FD exhaustion
agents
size: S
Cluster:
Skill Enhancements and Fixes
## Problem
The skills file watcher (`chokidar`) in `src/agents/skills/refresh.ts` watches the entire skills directory tree with `awaitWriteFinish` polling enabled. When a skill contains a large number of asset files (e.g. an SVG icon pack with 37,000+ files), chokidar opens one file descriptor per watched file for write-finish polling.
This causes **FD exhaustion on macOS**, eventually preventing the gateway from spawning child processes (`EBADF`).
### Observed behavior
- Gateway process accumulated **37,439 open file descriptors** overnight
- All FDs were REG (regular file) handles to SVG files in a single skill directory
- `exec` tool calls failed with `spawn EBADF`
- Gateway restart did not help — the FDs were opened immediately at startup
### Root cause
`ensureSkillsWatcher()` creates a chokidar watcher on skill directories with:
```js
awaitWriteFinish: {
stabilityThreshold: debounceMs,
pollInterval: 100,
}
```
The `awaitWriteFinish` option causes chokidar to poll files for stability, which requires opening a file descriptor for each watched file. The existing `ignored` patterns only excluded `.git`, `node_modules`, `dist`, and Python cache directories — not asset files.
## Fix
Add an allowlist of skill-relevant file extensions (`.md`, `.js`, `.ts`, `.json`, `.yaml`, `.py`, `.sh`, etc.) to the watcher's ignored patterns. Non-relevant files (images, SVGs, audio, video, fonts, archives, etc.) are now excluded from the watcher.
This keeps FD usage proportional to actual skill code rather than total asset count.
### Before
```
$ lsof -p $(pgrep -f openclaw-gateway) | wc -l
37439
```
### After
```
$ lsof -p $(pgrep -f openclaw-gateway) | wc -l
119
```
## Changes
- `src/agents/skills/refresh.ts`: Added `SKILLS_WATCH_RELEVANT_EXTENSIONS` allowlist and a filter function to `DEFAULT_SKILLS_WATCH_IGNORED`
- `src/agents/skills/refresh.test.ts`: Updated tests to handle mixed RegExp/function ignored array, added test for asset file filtering
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR updates the skills file watcher (`src/agents/skills/refresh.ts`) to avoid file-descriptor exhaustion by ignoring non-skill asset files and only watching skill-relevant file types. Tests in `src/agents/skills/refresh.test.ts` were updated to accommodate the new `ignored` rules (now supporting both RegExp and function predicates) and to assert that common asset extensions are ignored.
The change fits into the skills snapshot pipeline by reducing watcher churn/FD usage while preserving the existing behavior of bumping the skills snapshot version on relevant filesystem events, which is consumed by session snapshot refresh logic.
<h3>Confidence Score: 4/5</h3>
- This PR is likely safe to merge once the remaining placeholder reference is resolved.
- The watcher change is narrowly scoped and tests were updated accordingly. The only definite merge-blocker spotted in the diff is a placeholder issue URL left in a source comment, which should be replaced or removed to avoid shipping misleading references.
- src/agents/skills/refresh.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#8291: Fix: Add Python virtual environment ignore patterns to skills watcher
by vishaltandale00 · 2026-02-03
86.6%
#10016: fix: prevent FD exhaustion from skill watcher scanning artifact trees
by oldeucryptoboi · 2026-02-06
86.4%
#9595: fix(skills): ignore .venv, __pycache__, and .openclaw to prevent FD...
by amoghacloud · 2026-02-05
85.9%
#6777: fix(skills): ignore Python venvs and caches in skills watcher
by kirkluokun · 2026-02-02
85.6%
#11250: fix: expand skills watcher ignore list and improve session repair l...
by zhangzhefang-github · 2026-02-07
84.0%
#12076: fix(skills): recursive directory filtering to actually exclude venv...
by xiaoyaner0201 · 2026-02-08
83.3%
#16654: fix: refresh skills snapshot when managed skills change
by PhineasFleabottom · 2026-02-15
81.2%
#22306: Warn on malformed skill parsing failures in load path
by AIflow-Labs · 2026-02-21
79.8%
#5273: fix: skill frontmatter fixes + description improvements (35 skills)
by Terwox · 2026-01-31
78.9%
#23749: fix some issues
by tronpis · 2026-02-22
78.9%