Skip to content

fix(nodeenv): install npm from the registry tarball on Windows - #425

Merged
ekalinin merged 2 commits into
masterfrom
fix/win-npm-registry-tarball
Sep 29, 2026
Merged

ekalinin merged 2 commits into
masterfrom
fix/win-npm-registry-tarball

Conversation

@ekalinin

Copy link
Copy Markdown
Owner

Closes #310

What happens

install_npm_win, which --with-npm uses on Windows and Cygwin, downloaded github.com/npm/cli/archive/v<ver>.zip: the source repository of npm, not the published package. That tree is not an installable npm:

  • npm 8.x links its workspaces into node_modules with symlinks. A GitHub zip stores a symlink as a file holding its target, and zipfile.extractall writes it out as such, so node_modules/libnpmfund becomes a text file containing ../workspaces/libnpmfund and npm dies with Unexpected token '.', the error from the issue.
  • npm >= 9 has no workspace packages in node_modules at all, so even npm --version fails with Cannot find module '@npmcli/config'.
  • The default --npm=latest asked for archive/vlatest.zip, which is a 404.

Unpacked the way install_npm_win did, npm 8.3.1, 8.19.4, 9.9.4, 10.9.9, 11.20.0 and 12.1.0 are all broken, while the registry tarball of each one works.

What changes

  • The version or dist-tag is resolved through registry.npmjs.org/npm/<spec>, and the tarball its dist.tarball points to is unpacked, with filter='data' on Python >= 3.12 as for the node archive.
  • The tarball ships bin/npm, so the Cygwin branch copies it instead of downloading it from raw.githubusercontent.com.

Tests

  • TestInstallNpmWin pinned the old implementation with mocks (the GitHub URL, the zipfile calls, cli-<ver>). It now serves a fake registry with a real .tgz and checks the files that end up in the environment: the published package for a version and for latest, a reinstall over an existing npm, the Cygwin bin/npm, and the refusal of a member pointing out of the unpack directory.
  • test_smoke_with_npm_win builds an environment with the command from the issue (--node=17.4.0 --npm=8.3.1) and with the default --npm=latest, runs activate.bat, then npm install in a project, and checks that the npm that answered is the one in the environment. It runs in a new with-npm-windows job, since the ubuntu integration job never takes install_npm_win.

The test commit was pushed on its own first: with-npm-windows failed with npm ERR! Unexpected token '.' for the issue case and with the vlatest.zip 404 for the default one, while the other 19 jobs passed. With the fix all 20 jobs are green.

--with-npm takes install_npm_win on Windows, a path the ubuntu
integration job never reaches, so a broken npm there went unnoticed
(#310). The new job builds an environment with the command from the
issue (--node=17.4.0 --npm=8.3.1) and with the default --npm=latest,
then runs activate.bat and `npm install` in a project, as the reporter
did.
install_npm_win downloaded github.com/npm/cli/archive/v<ver>.zip, the
source repository of npm rather than the published package. That tree is
not an installable npm:

- npm 8.x links its workspaces into node_modules with symlinks, and
  zipfile.extractall writes them as text files holding the link target,
  so npm dies with "Unexpected token '.'" on node_modules/libnpmfund
- npm >= 9 has no workspace packages in node_modules at all, so even
  `npm --version` fails with "Cannot find module '@npmcli/config'"
- the default --npm=latest asked for archive/vlatest.zip, a 404

Resolve the version or dist-tag through registry.npmjs.org and unpack
the tarball its metadata points to, with filter='data' as for the node
archive. The tarball carries bin/npm too, so the Cygwin branch copies it
instead of fetching it from raw.githubusercontent.com.

The mock-based TestInstallNpmWin tests pinned the GitHub URL and zipfile
calls; they now run the real unpacking against a fake registry.

Fixes #310
@ekalinin
ekalinin merged commit 3e50b5c into master Sep 29, 2026
46 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unexpected token '.' when running npm install with node 17.4.0 and explicit npm installation

1 participant