Current Behavior
🐛 Bug: disposeFn is not a function when terminating @nx/js:swc with watch mode
Description
When using the @nx/js:swc executor with watch: true, pressing Ctrl+C to terminate the process throws the following error:
TypeError: disposeFn is not a function
at process.<anonymous> (.../node_modules/@nx/js/src/executors/swc/swc.impl.js:111:36)
This seems to occur when the build fails or watcher logic did not initialize disposeFn.
🔁 Reproduction Steps
- Use
@nx/js:swc executor in a project with "watch": true
- Trigger a build that fails (e.g. bad import or syntax error)
- While watching, press
Ctrl+C
- Observe the error
💡 Expected Behavior
Graceful exit without errors, even if build fails or disposeFn is undefined.
📁 Example project.json
{
"name": "example",
"sourceRoot": "packages/example/src",
"targets": {
"build": {
"executor": "@nx/js:swc",
"options": {
"main": "packages/example/src/index.ts",
"outputPath": "packages/example/dist",
"tsConfig": "packages/example/tsconfig.lib.json",
"skipTypeCheck": true,
"stripLeadingPaths": true
}
},
"serve": {
"executor": "@nx/js:node",
"options": {
"buildTarget": "example:build",
"watch": true
}
}
}
}
📦 Environment Info
- Nx version: 21.2.3
- Node version: 24.3.0
- OS: macOS
- Package causing issue:
@nx/js (specifically swc.impl.js)
✅ Suggested Fix
Wrap the disposeFn() call with a type check or provide a no-op fallback:
process.on('SIGINT', () => {
if (typeof disposeFn === 'function') {
disposeFn();
}
});
Expected Behavior
When using the @nx/js:swc executor with "watch": true, terminating the process via SIGINT (e.g. pressing Ctrl+C) should gracefully shut down without throwing errors — regardless of build success or failure.
Specifically:
- If
disposeFn was not initialized (e.g. due to an early build failure), the watcher should still exit cleanly.
- The executor should verify that
disposeFn is defined and is a function before calling it.
- No unhandled exceptions should occur during termination.
- Developer experience should remain smooth and predictable even in edge cases like early failures or manual termination.
GitHub Repo
No response
Steps to Reproduce
Nx Report
1. Create a project using the `@nx/js:swc` executor for the `build` target.
2. In your `serve` target, use the `@nx/js:node` executor with `watch: true` and reference the build target.
3. Introduce an error in your source code — for example, a broken import or invalid syntax in `src/index.ts`.
4. From the root directory, run the serve command:
pnpm nx run example:serve
5. You will see:
Build failed, waiting for changes to restart...
6. While watching, press `Ctrl+C` to terminate the process.
7. Observe the following error in the terminal:
TypeError: disposeFn is not a function
This sequence consistently triggers the bug in environments using Nx `21.2.3` + Node `24.3.0` with `@nx/js:swc`.
Failure Logs
Package Manager Version
No response
Operating System
Additional Information
No response
Current Behavior
🐛 Bug:
disposeFn is not a functionwhen terminating@nx/js:swcwith watch modeDescription
When using the
@nx/js:swcexecutor withwatch: true, pressingCtrl+Cto terminate the process throws the following error:This seems to occur when the build fails or watcher logic did not initialize
disposeFn.🔁 Reproduction Steps
@nx/js:swcexecutor in a project with"watch": trueCtrl+C💡 Expected Behavior
Graceful exit without errors, even if build fails or
disposeFnis undefined.📁 Example
project.json{ "name": "example", "sourceRoot": "packages/example/src", "targets": { "build": { "executor": "@nx/js:swc", "options": { "main": "packages/example/src/index.ts", "outputPath": "packages/example/dist", "tsConfig": "packages/example/tsconfig.lib.json", "skipTypeCheck": true, "stripLeadingPaths": true } }, "serve": { "executor": "@nx/js:node", "options": { "buildTarget": "example:build", "watch": true } } } }📦 Environment Info
@nx/js(specificallyswc.impl.js)✅ Suggested Fix
Wrap the
disposeFn()call with a type check or provide a no-op fallback:Expected Behavior
When using the
@nx/js:swcexecutor with"watch": true, terminating the process viaSIGINT(e.g. pressing Ctrl+C) should gracefully shut down without throwing errors — regardless of build success or failure.Specifically:
disposeFnwas not initialized (e.g. due to an early build failure), the watcher should still exit cleanly.disposeFnis defined and is a function before calling it.GitHub Repo
No response
Steps to Reproduce
Nx Report
Failure Logs
Package Manager Version
No response
Operating System
Additional Information
No response