Repository navigation
fix(unpublish): refuse to unpublish a version when the registry returns no versions - #10117
Open
meganemura wants to merge 2 commits into
Open
meganemura wants to merge 2 commits into
meganemura wants to merge 2 commits into
Conversation
`npm unpublish <pkg>@<version>` refuses to delete the last version without --force, but the check read the abbreviated packument while libnpmpublish decides from the full one. When the abbreviated document listed a version the full one did not, the check passed and libnpmpublish deleted the whole package. A full packument with no versions also passed the check and deleted the whole package. Read the full packument for the check, and treat no versions as the last version. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CykpGv4PTktW9jr8y5EYkR
nkolev92
reviewed
Oct 15, 2026
|
|
||
| const versions = await Unpublish.getKeysOfVersions(spec.name, opts) | ||
| if (versions.length === 1 && spec.rawSpec === versions[0] && !force) { | ||
| const lastVersion = versions.length === 0 || |
There was a problem hiding this comment.
versions length 0 seems like something that shouldn't be happening.
I feel like this should be an unconditional failure.
Curious to get your thoughts @reggi
Author
There was a problem hiding this comment.
@nkolev92
Agreed. It now fails unconditionally, even with --force, when a version is specified and the registry returns no versions. Whole-package unpublish is unchanged.
…ns no versions When a specific version is requested and the registry returns a packument with no versions, libnpmpublish deletes the whole package. Refuse instead, even with --force, since the requested version cannot be verified. Drop the fullMetadata read: the full and abbreviated packuments are expected to agree, and it did not change the outcome. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XZoh3ni1qhXKcwpBwN5bP
Author
|
I’ve pushed the changes and updated the PR title and description to match. |
nkolev92
approved these changes
Oct 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
npm unpublish <pkg>@<version>reads the packument with?write=trueto check the versions. When that packument has no versions, the command passes the check, andlibnpmpublishthen deletes the whole package instead of the one version. With--force, the same thing happens. A packument with noversionsfield throwsTypeError: Cannot convert undefined or null to objectinstead.I saw this through a registry proxy (Aikido safe-chain) that filtered all versions out of the
?write=truereads.This change:
--force;versionsfield as empty instead of throwing.Unpublishing the whole package (
npm unpublish <pkg> --force,<pkg>@*) does not change.The two new tests (no
versionsfield, and emptyversionswith--force) fail without the change.References
Fixes #10116
Related to #4924, #7015
🤖 Generated with Claude Code