Skip to content

[BUG] regression, npm publish folder has a new and completely incompatible behaviour where folder is interpreted as a package name and is then fetched from the registry #4126

@cormacrelf

Description

@cormacrelf

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

npm publish folder syntax has stopped working almost completely if the folder is not prefixed with a ./ and is not an absolute path. Not only has it stopped working, it is doing utter nonsense, and is producing really weird output as outlined in the repro section below. So much so it no longer appears to be doing anything recognisable as publishing a package at all.

This is a rather critical piece of functionality that is going to break a bunch of scripts all over the internet. I personally found this bug when an unchanged Github Actions workflow stopped publishing canary builds of my package.

The syntax I have used there is npm publish dist --access public --tag canary. The package has been built correctly into a directory named dist, and it has a package.json with a name (that is not dist but @citeproc-rs/wasm). For the past year, this script successfully published dozens of versions of the package, but today it does not. It now fails with an ETARGET message, saying that the package/version dist@canary could not be found. This is completely unexpected, not only because it worked before, but because there is no documented syntax of npm publish where any command line argument accepts a package name. That has always been implied from the package.json!

The Steps to Reproduce below has a guided tour of the insanity that is going on with npm publish.

Expected Behavior

npm publish folder should publish a folder!!! Even if that were not literally the documented syntax of the command, you would expect it to fail with a mysterious error message like ETARGET or a 404. There is no such documented syntax npm publish packagename! Why would it try looking it up on the registry!!!

Steps To Reproduce

  1. mkdir folder
  2. Put a package.json inside it, with "name": "asdfasdfasdf-nonexistent-package"
  3. Observe that the documentation says the syntax is npm publish [<tarball>|<folder>], no mention of folder being a package name
  4. Attempt npm publish folder --dry-run with npm 8.2.0

Watch, in horror, as NPM appears to download the tarball for package folder@0.0.4, list out its contents, and print the summary of the tarball. There is zero relation between doing this and npm publish. I am absolutely speechless.

npm notice
npm notice 📦  folder@0.0.4
npm notice === Tarball Contents ===
npm notice 14B   .npmignore
npm notice 263B  README.md
npm notice 4.9kB lib/html.js
npm notice 2.8kB lib/index.js
npm notice 321B  package.json
...
npm notice === Tarball Details ===
npm notice name:          folder
npm notice version:       0.0.4
npm notice filename:      folder-0.0.4.tgz
npm notice package size:  206.8 kB
npm notice unpacked size: 226.1 kB
npm notice shasum:        56dc666bd686e2f029055e938a003f0f2fadc225
npm notice integrity:     sha512-drevPjCcenZ7O[...]monYcuEYiMK3A==
npm notice total files:   146
npm notice
+ folder@0.0.4

It goes on. The behaviour is different if the name of the directory is not an existing package in the registry.

  1. mv folder asdfasdfasdf-nonexistent-package
  2. npm publish asdfasdfasdf-nonexistent-package --dry-run

Receive:

npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/asdfasdfasdf-nonexistent-package - Not found
npm ERR! 404
npm ERR! 404  'asdfasdfasdf-nonexistent-package@latest' is not in this registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.

There's a THIRD variation. This is when the name of the folder is an existing package on the registry, but you're using the --tag flag, and the package of that name (again, COMPLETELY irrelevant, NPM should not be looking it up at all) does not have that tag. It is relevant to post here because you get more completely different output.

  1. Rename the directory back to folder
  2. npm publish folder --dry-run --tag canary
npm ERR! code ETARGET
npm ERR! notarget No matching version found for folder@canary.
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.

There is a workaround: use the syntax npm publish ./folder. Then it knows the folder is a folder.

Environment

  • npm: v8.2.0
  • Node: v17.0.1
  • OS: macOS 12.0.1
  • platform: Macbook Pro
  • npm config:
; "builtin" config from /opt/homebrew/lib/node_modules/npm/npmrc

prefix = "/opt/homebrew"

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

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

; node bin location = /opt/homebrew/Cellar/node/17.0.1/bin/node
; cwd = /Users/me/git/temporary
; HOME = /Users/me
; Run `npm config ls -l` to show all defaults

Metadata

Metadata

Assignees

Labels

Bugthing that needs fixingDiscusswill be discussed at the next internal callPriority 0will get attention right awayRelease 8.xwork is associated with a specific npm 8 release

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions