Skip to content

disposeFn is not a function when terminating @nx/js:swc with watch mode #31938

@yxqme

Description

@yxqme

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

  1. Use @nx/js:swc executor in a project with "watch": true
  2. Trigger a build that fails (e.g. bad import or syntax error)
  3. While watching, press Ctrl+C
  4. 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

  • macOS
  • Linux
  • Windows
  • Other (Please specify)

Additional Information

No response

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions