-
-
Notifications
You must be signed in to change notification settings - Fork 10
Description
Description
When running cmk --watch on a real-world project with many npm dependencies, I get continuous EMFILE: too many open files errors.
This issue is more likely to occur in:
- Projects with many npm packages installed (large
node_modules) - Real production projects rather than minimal test setups
Environment:
- OS: macOS (default file descriptor limit: 256)
- Node.js: v22.x
- @css-modules-kit/codegen: 0.8.1
- Number of packages in node_modules: ~800+ (typical Next.js + Storybook project)
tsconfig.json:
{
"include": [
"**/*.module.css",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"**/node_modules/**"
]
}Error:
Error: EMFILE: too many open files, watch
at FSWatcher._handle.onchange (node:internal/fs/watchers:214:21)
Why This Matters
This issue may not be reproducible in minimal test projects because:
- Small projects have few directories in
node_modules - macOS default file descriptor limit (256) is only exceeded when watching many directories
- The problem scales with the number of installed packages
In our project, node_modules contains approximately 2000+ files/directories, which quickly exhausts the file descriptor limit.
Root Cause Analysis
I debugged the issue and found the following:
-
TypeScript's
parseJsonSourceFileConfigFileContentreturnswildcardDirectoriescontaining the project root withrecursive: truewhen include patterns like**/*.module.cssare used. -
In
runner.ts, thesewildcardDirectoriesare passed directly to chokidar without considering tsconfig'sexcludepatterns. -
The
ignoredfunction in chokidar options returnsfalsewhenstatsis undefined (first call), which means all directories includingnode_modulesare initially watched before being filtered. -
Chokidar creates fs.watch handles for every subdirectory before the ignored function can filter them out, exhausting file descriptor limits on projects with many dependencies.
Debug output showing the issue:
wildcardDirectories: [
{
"fileName": "/path/to/project",
"recursive": true
}
]
Expected Behavior
cmk --watch should respect tsconfig.json's exclude patterns when determining which directories to watch.
This would prevent watching node_modules and allow the tool to work on real-world projects without requiring users to increase system file descriptor limits.
Workaround
Changing tsconfig.json include patterns to use explicit directory prefixes works around the issue:
{
"include": [
"src/**/*.module.css",
"src/**/*.ts"
]
}However, this requires users to change their tsconfig.json structure, which may not always be desirable.