Commit d39a716
fix(core): resolve false positive loop detection when running with Bun (#34640)
Bun includes extra consecutive async frames for async functions in call
stacks, causing `preventRecursionInGraphConstruction` to falsely detect
a recursive loop during normal project graph construction.
## Root Cause
`preventRecursionInGraphConstruction` uses `getCallSites().slice(2)` to
skip the top 2 frames (itself +
`buildProjectGraphAndSourceMapsWithoutDaemon`), then checks if
`buildProjectGraphAndSourceMapsWithoutDaemon` appears again in the
remaining frames.
In Bun, `buildProjectGraphAndSourceMapsWithoutDaemon` appears **twice
consecutively** due to async frame duplication — leaving one occurrence
after the slice, which incorrectly triggers the loop error.
**Node call stack (after `slice(2)`):**
```
#0 createProjectGraphAndSourceMapsAsync ← clean
#1 createProjectGraphAsync
#2 runOne
```
**Bun call stack (after `slice(2)`):**
```
#0 buildProjectGraphAndSourceMapsWithoutDaemon ← false positive!
#1 createProjectGraphAndSourceMapsAsync
#2 createProjectGraphAndSourceMapsAsync ← Bun duplicates async frames
#3 createProjectGraphAsync
```
## Fix
Since the call stack recursion check does not work reliably under Bun,
`preventRecursionInGraphConstruction` now returns early when running
under Bun, detected via `'Bun' in globalThis` — consistent with the
existing Bun runtime detection pattern used elsewhere in the codebase
(e.g., `isolated-plugin.ts`). The original `slice(2)` logic is preserved
unchanged for Node.js and other runtimes.
```ts
export function preventRecursionInGraphConstruction() {
// Bun's async stack traces include extra frames that cause false positives in the
// recursion check below, so we skip the check when running under Bun.
if ('Bun' in globalThis) {
return;
}
// ... existing Node.js check ...
}
```
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
----
*This section details on the original issue you should resolve*
<issue_title>getCallSites output differs between Node and Bun triggering
loop detection</issue_title>
<issue_description>### Current Behavior
Hey team,
I am trying to use Bun (1.3.5) instead of Node (v22.17.0) for running Nx
(v22.1.3) and bumped into the following error:
Command:
```bash
bunx --bun nx run api:build
```
Error:
```
NX Project graph construction cannot be performed due to a loop detected in the call stack. This can happen if 'createProjectGraphAsync' is called directly or indirectly during project graph construction.
To avoid this, you can add a check against "global.NX_GRAPH_CREATION" before calling "createProjectGraphAsync".
Call stack:
buildProjectGraphAndSourceMapsWithoutDaemon (/app/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]__@[email protected]_t_twtgkxomntuzxcyp4ewkmtxn2q/node_modules/nx/src/project-graph/project-graph.js:81:62)
createProjectGraphAndSourceMapsAsync (/app/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]__@[email protected]_t_twtgkxomntuzxcyp4ewkmtxn2q/node_modules/nx/src/project-graph/project-graph.js:274:31)
createProjectGraphAndSourceMapsAsync (/app/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]__@[email protected]_t_twtgkxomntuzxcyp4ewkmtxn2q/node_modules/nx/src/project-graph/project-graph.js:225:53)
createProjectGraphAsync (/app/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]__@[email protected]_t_twtgkxomntuzxcyp4ewkmtxn2q/node_modules/nx/src/project-graph/project-graph.js:222:45)
createProjectGraphAsync (/app/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]__@[email protected]_t_twtgkxomntuzxcyp4ewkmtxn2q/node_modules/nx/src/project-graph/project-graph.js:205:40)
runOne (/app/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]__@[email protected]_t_twtgkxomntuzxcyp4ewkmtxn2q/node_modules/nx/src/command-line/run/run-one.js:23:52)
runOne (/app/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]__@[email protected]_t_twtgkxomntuzxcyp4ewkmtxn2q/node_modules/nx/src/command-line/run/run-one.js:16:23)
Pass --verbose to see the stacktrace.
```
After some digging I found that the stack trace produced by
https://github.com/nrwl/nx/blob/691bb320ce1e9cc2872e1a1b364d3fdeb9e1ad0e/packages/nx/src/utils/call-sites.ts
differs between Node and Bun. When
https://github.com/nrwl/nx/blob/691bb320ce1e9cc2872e1a1b364d3fdeb9e1ad0e/packages/nx/src/project-graph/project-graph.ts#L422
is run, the produced function call tracing is:
Node (v22.17.0):
```
nrwl/nx#0 createProjectGraphAndSourceMapsAsync
#1 createProjectGraphAsync
#2 runOne
#3 <anonymous>
#4 <anonymous>
#5 handleErrors
#6 handler
```
Bun (1.3.5):
```
nrwl/nx#0 buildProjectGraphAndSourceMapsWithoutDaemon <- This entry causes Nx to detect a loop
#1 createProjectGraphAndSourceMapsAsync
#2 createProjectGraphAndSourceMapsAsync
#3 createProjectGraphAsync
#4 createProjectGraphAsync
#5 runOne
#6 runOne
```
This is not a Nx bug per-se, but wondering if this falls into the
efforts of supporting Bun into Nx (i.e.
https://nx.dev/blog/nx-19-5-adds-stackblitz-new-features-and-more#bun-and-pnpm-v9-support)?
I will cross post the above into the Bun repo too for input.
### Expected Behavior
Able to execute Nx commands with Bun
### GitHub Repo
_No response_
### Steps to Reproduce
1. Run bunx --bun nx run api:build
### Nx Report
```shell
NX_DAEMON=true bunx --bun nx --disableNxCache --disableRemoteCache --outputStyle dynamic-legacy report 1 ✘ 16:18:00
NX Report complete - copy this into the issue template
Node : 24.3.0
OS : darwin-arm64
Native Target : aarch64-macos
pnpm : 9.6.0
nx : 22.1.3
@nx/js : 22.1.3
@nx/jest : 22.1.3
@nx/eslint : 22.1.3
@nx/workspace : 22.1.3
@nx/cypress : 22.1.3
@nx/devkit : 22.1.3
@nx/esbuild : 22.1.3
@nx/eslint-plugin : 22.1.3
@nx/module-federation : 22.1.3
@nx/nest : 22.1.3
@nx/next : 22.1.3
@nx/node : 22.1.3
@nx/playwright : 22.1.3
@nx/plugin : 22.1.3
@nx/react : 22.1.3
@nx/rollup : 22.1.3
@nx/storybook : 22.1.3
@nx/vite : 22.1.3
@nx/vitest : 22.1.3
@nx/web : 22.1.3
@nx/webpack : 22.1.3
@nx/docker : 22.1.3
nx-cloud : 19.1.0
@nrwl/nx-cloud : 19.1.0
typescript : 5.7.3
---------------------------------------
Registered Plugins:
@nxlv/python
---------------------------------------
Community plu...
</details>
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes #33997
<!-- START COPILOT CODING AGENT TIPS -->
---
✨ Let Copilot coding agent [set things up for you](https://github.com/nrwl/nx/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.
---------
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: AgentEnder <[email protected]>
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
Co-authored-by: Copilot <[email protected]>
(cherry picked from commit c89dd93)1 parent 0e39831 commit d39a716
1 file changed
Lines changed: 30 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
416 | 416 | | |
417 | 417 | | |
418 | 418 | | |
419 | | - | |
420 | | - | |
421 | | - | |
422 | | - | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
423 | 449 | | |
424 | 450 | | |
425 | 451 | | |
| |||
0 commit comments