-
-
Notifications
You must be signed in to change notification settings - Fork 69.6k
[Bug]: plugin discovery scans into node_modules/browser_data causing FD exhaustion and spawn EBADF (reproducible on 2026.3.11) #43813
Description
Summary
shouldIgnoreScannedDirectory() in src/plugins/discovery.ts only skips .bak/.backup-/.disabled directories. It does not skip node_modules, .git, .venv, browser_data, or any other heavy dependency/build directories.
When a workspace skill or plugin contains node_modules, the plugin discovery scanner descends into every subdirectory and probes for package manifests via openBoundaryFileSync. This exhausts the process file descriptor table on macOS and causes spawn EBADF (errno -9) on all subsequent exec tool calls.
The skills watcher (DEFAULT_SKILLS_WATCH_IGNORED in refresh.ts) and memory watcher (IGNORED_MEMORY_WATCH_DIR_NAMES in manager-sync-ops.ts) already ignore these directories — but the plugin discovery scanner does not.
Environment
- OpenClaw: 2026.3.11 (29dc654) — latest release
- OS: macOS (Darwin, arm64)
- Node.js: v22.22.1
Steps to Reproduce
- Install a skill/plugin that has its own
node_modules(e.g.memory-lancedb-prowith ~5,000 files innode_modules/) - Start the gateway:
openclaw gateway start - Check FD count:
lsof -p $(pgrep openclaw-gateway) | wc -l - Observe 12,000+ open file descriptors, mostly REG (regular file) in read-only mode
- Attempt any
exectool call → fails withspawn EBADF
Expected Behavior
Plugin discovery should skip node_modules, .git, .venv, and other directories that cannot contain valid plugins. FD count should stay in the hundreds, not thousands.
Actual Behavior
$ lsof -p $(pgrep openclaw-gateway) | wc -l
12232
$ lsof -p $(pgrep openclaw-gateway) | awk '{print $NF}' | grep node_modules | wc -l
8595
All exec calls fail with spawn EBADF.
Root Cause
src/plugins/discovery.ts, function shouldIgnoreScannedDirectory():
function shouldIgnoreScannedDirectory(dirName: string): boolean {
const normalized = dirName.trim().toLowerCase();
if (!normalized) return true;
if (normalized.endsWith(".bak")) return true; // ← only these
if (normalized.includes(".backup-")) return true; // ← three
if (normalized.includes(".disabled")) return true; // ← patterns
return false;
}This function is called by discoverInDirectory() which recurses into every subdirectory of plugin roots. Without node_modules in the skip list, it enters dependency trees with thousands of packages.
Compare with the skills watcher (DEFAULT_SKILLS_WATCH_IGNORED) which already ignores node_modules, .git, dist, .venv, venv, __pycache__, .mypy_cache, .pytest_cache, build, .cache.
Workaround
Manually delete node_modules from workspace skills and restart the gateway. FD count drops from 12,232 to 1,231.
Previously
- [Bug]:
spawn EBADFerror on all exec tool calls** #2532 — originalspawn EBADFtracking issue - fix: prevent file descriptor leak from Python venv directories in skills #8869 — attempted fix for skills watcher venv ignore (closed as stale; maintainer noted: "If the underlying bug is still reproducible on current main, open a new focused fix PR")
- File descriptor leak in workspace scanning on every message #11181 — FD leak in workspace scanning on every message