NX @nx/vite:build executor resolves outputPath outside workspace root
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Problem Statement
The @nx/vite:build executor in @nx/vite (v21.6.9) miscalculates the outDir passed to Vite, causing build output to be written outside the workspace directory. This affects the edit-content-bridge project and potentially any Vite-based library nested more than one level deep.
Root cause (in node_modules/@nx/vite/src/executors/build/build.impl.js, line 29):
const outDir = joinPathFragments(offsetFromRoot(projectRoot), options.outputPath)
?? resolved?.build?.outDir;
For edit-content-bridge at libs/edit-content-bridge:
offsetFromRoot("libs/edit-content-bridge")→"../../"options.outputPath→"dist/libs/edit-content-bridge"- Result:
"../../dist/libs/edit-content-bridge"(relative path)
This relative path is passed to Vite via mergeConfig, overriding the correct absolute path already set in vite.config.ts. Vite then resolves this relative path against its root (the workspace root /path/to/core-web), producing:
/path/to/core-web/../../dist/libs/edit-content-bridge → /path/dist/libs/edit-content-bridge
This writes output two directories above the workspace. The vite.config.ts already handles path resolution correctly using resolve(__dirname, ...), but the executor override defeats it.
Steps to Reproduce
- Reset NX cache:
cd core-web && npx nx reset && rm -rf dist .nx - Build the affected project:
npx nx build edit-content-bridge - Observe the error:
(!) outDir /dist/libs/edit-content-bridge is not inside project root and will not be emptied.
EACCES: permission denied, mkdir '/dist'
The exact misplaced path depends on where the workspace is cloned. For a workspace at /home/user/code/core/core-web, output would land at /home/user/code/dist/libs/edit-content-bridge.
Expected Behavior
Build output should go to core-web/dist/libs/edit-content-bridge (inside the workspace).
Actual Behavior
Build output is directed to a path outside the workspace, calculated by walking up from the workspace root by the depth of the project folder. On CI or containerized environments where the ancestor directory is not writable, the build fails outright.
Acceptance Criteria
-
npx nx build edit-content-bridge(with empty NX cache) writes output tocore-web/dist/libs/edit-content-bridge - No files are created outside the
core-web/workspace directory - Full Maven build (
./mvnw install -DskipTests) succeeds with empty NX cache
dotCMS Version
Latest from main branch (NX 21.6.9, @nx/vite 21.6.9, Vite 7.2.7)
Severity
Medium - Some functionality impacted
The build succeeds once NX cache is populated (e.g. from a previous successful build). It only fails on cold-cache builds or CI environments. Workaround: create the misplaced target directory, or pre-populate NX cache.
Links
- NX vite executor source:
node_modules/@nx/vite/src/executors/build/build.impl.jsline 29 - Affected project config:
core-web/libs/edit-content-bridge/project.json - Vite config (correct resolution):
core-web/libs/edit-content-bridge/vite.config.ts - NA (no Freshdesk ticket)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with node_modules/@nx/vite/src/executors/build/build.impl.js at line 29, then compare its outputPath handling with core-web/libs/edit-content-bridge/project.json and vite.config.ts. Run the cache-cleared npx nx build edit-content-bridge reproduction and verify that output stays in core-web/dist/libs/edit-content-bridge, with no files created outside the workspace; then check the Maven command listed in the acceptance criteria.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, typescript
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100