Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Yarn workspaces w/ Symlinks Breaks npx Invocations #7834

Closed
2 tasks done
brianlenz opened this issue Oct 14, 2024 · 5 comments · Fixed by npm/map-workspaces#176
Closed
2 tasks done

[BUG] Yarn workspaces w/ Symlinks Breaks npx Invocations #7834

brianlenz opened this issue Oct 14, 2024 · 5 comments · Fixed by npm/map-workspaces#176
Labels
Bug thing that needs fixing Needs Triage needs review for next steps

Comments

@brianlenz
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

This issue exists in the latest npm version

  • I am using the latest npm

Current Behavior

I've had issues invoking a couple of different commands due to the existence of symbolic links in our monorepo using Yarn workspaces. Specifically, I've gotten the error with npx @react-native-vector-icons/codemod and npx @react-native-community/cli config.

I had originally thought it was a bug in @react-native-community/cli and filed a bug there, but then I had the same issue with @react-native-vector-icons/codemod and realized it might be an npx bug, which is why I'm reporting the issue here now.

Expected Behavior

The existence of symbolic links in a monorepo should not break npx commands.

Steps To Reproduce

  1. Clone this git repo: https://github.com/brianlenz/rncli-symlink-bug
  2. Run npx @react-native-community/cli config in the root of the repo or in testsymlinkproj.
  3. Observe error:
Exit prior to config file resolving
cause
Could not read package.json: Error: ENOTDIR: not a directory, open '.../testsymlinkmonorepo/scripts/script-a/src/index.js/package.json'

or

npm error code ENOTDIR
npm error syscall open
npm error path .../testsymlinkmonorepo/scripts/script-a/src/index.js/package.json
npm error errno -20
npm error Could not read package.json: Error: ENOTDIR: not a directory, open '.../testsymlinkmonorepo/scripts/script-a/src/index.js/package.json'
npm error A complete log of this run can be found in: /Users/brian/.npm/_logs/2024-10-14T18_48_40_227Z-debug-0.log

The log detail:

0 verbose cli /opt/homebrew/Cellar/node/22.9.0_1/bin/node /opt/homebrew/lib/node_modules/npm/bin/npm-cli.js
1 info using [email protected]
2 info using [email protected]
3 silly config load:file:/opt/homebrew/lib/node_modules/npm/npmrc
4 silly config load:file:.../testsymlinkmonorepo/.npmrc
5 silly config load:file:/Users/brian/.npmrc
6 silly config load:file:/opt/homebrew/etc/npmrc
7 verbose title npm exec @react-native-community/cli config
8 verbose argv "exec" "--" "@react-native-community/cli" "config"
9 verbose logfile logs-max:10 dir:/Users/brian/.npm/_logs/2024-10-14T18_48_40_227Z-
10 verbose logfile /Users/brian/.npm/_logs/2024-10-14T18_48_40_227Z-debug-0.log
11 silly logfile start cleaning logs, removing 1 files
12 silly logfile done cleaning log files
13 silly packumentCache heap:4345298944 maxSize:1086324736 maxEntrySize:543162368
14 verbose stack Error: Could not read package.json: Error: ENOTDIR: not a directory, open '.../testsymlinkmonorepo/scripts/script-a/src/index.js/package.json'
14 verbose stack     at async open (node:internal/fs/promises:638:25)
14 verbose stack     at async readFile (node:internal/fs/promises:1238:14)
14 verbose stack     at async read (/opt/homebrew/lib/node_modules/npm/node_modules/@npmcli/package-json/lib/read-package.js:9:18)
14 verbose stack     at async PackageJson.load (/opt/homebrew/lib/node_modules/npm/node_modules/@npmcli/package-json/lib/index.js:130:31)
14 verbose stack     at async PackageJson.normalize (/opt/homebrew/lib/node_modules/npm/node_modules/@npmcli/package-json/lib/index.js:116:5)
14 verbose stack     at async mapWorkspaces (/opt/homebrew/lib/node_modules/npm/node_modules/@npmcli/map-workspaces/lib/index.js:135:13)
14 verbose stack     at async [setWorkspaces] (/opt/homebrew/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/index.js:208:24)
14 verbose stack     at async #loadActual (/opt/homebrew/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/load-actual.js:172:5)
14 verbose stack     at async exec (/opt/homebrew/lib/node_modules/npm/node_modules/libnpmexec/lib/index.js:175:21)
14 verbose stack     at async Npm.exec (/opt/homebrew/lib/node_modules/npm/lib/npm.js:207:9)
15 error code ENOTDIR
16 error syscall open
17 error path .../testsymlinkmonorepo/scripts/script-a/src/index.js/package.json
18 error errno -20
19 error Could not read package.json: Error: ENOTDIR: not a directory, open '.../testsymlinkmonorepo/scripts/script-a/src/index.js/package.json'
20 verbose cwd .../testsymlinkmonorepo
21 verbose os Darwin 24.0.0
22 verbose node v22.9.0
23 verbose npm  v10.9.0
24 verbose exit -20
25 verbose code -20
26 error A complete log of this run can be found in: /Users/brian/.npm/_logs/2024-10-14T18_48_40_227Z-debug-0.log

Environment

  • npm: 10.9.0
  • Node.js: 22.9.0
  • OS Name: macOS
  • System Model Name: Macbook Pro
  • npm config:
; "builtin" config from /opt/homebrew/lib/node_modules/npm/npmrc

prefix = "/opt/homebrew"

; "user" config from /Users/brian/.npmrc

//registry.npmjs.org/:_authToken = (protected)

; node bin location = /opt/homebrew/Cellar/node/22.9.0_1/bin/node
; node version = v22.9.0
; npm local prefix = /Users/brian
; npm version = 10.9.0
; cwd = /Users/brian
; HOME = /Users/brian
; Run `npm config ls -l` to show all defaults.
@milaninfy
Copy link
Contributor

in your workspace definition of package.json

"workspaces": [
    "scripts/*",       // instead of **, could you try with * 
    "testsymlinkproj"
  ]
  

@brianlenz
Copy link
Author

@milaninfy sorry for the delay! Yes, it appears that changing that workspace config to /* instead of /** works around the issue. Unfortunately, this isn't a viable solution for us, as we have deeply nested projects in the scripts directory in our monorepo that we need to use Yarn workspaces (thus the ** is a necessity). But hopefully that information is helpful to trace and fix the bug! 🙏

@milaninfy
Copy link
Contributor

I don't think it's a bug yet 😄
** recursively finds all folders as workspaces. I believe that's not the case with your project, as I understand it's deeply nested but not all folders are workspaces.

@brianlenz
Copy link
Author

@milaninfy the configuration works perfectly from a Yarn workspaces standpoint, so I don't think that's the issue at all. Why is npx treating a symbolic link to a file as a folder (and thus a new workspace)? It's just a file, but npx seems to be looking for a package.json file within a file (which obviously doesn't make any sense). To be clear, just look at this path: .../testsymlinkmonorepo/scripts/script-a/src/index.js/package.json. Of course this package.json doesn't exist because index.js is a symbolic link to a file 😁

Please check out this repo that reproduces the issue, and you can see how simple the use case is: https://github.com/brianlenz/rncli-symlink-bug

Based on the stack trace, it looks like it's probably a bug in https://github.com/npm/map-workspaces.

One way to address this is here: https://github.com/npm/map-workspaces/blob/main/lib/index.js#L137

-      if (err.code === 'ENOENT') {
+      if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {

This solves the problem. Is there anything problematic about this approach?

@brianlenz
Copy link
Author

I went ahead and opened a PR here for further consideration / discussion 🙏

npm/map-workspaces#176

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug thing that needs fixing Needs Triage needs review for next steps
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants