Replies: 2 comments
|
💬 Your Product Feedback Has Been Submitted 🎉 Thank you for taking the time to share your insights with us! Your feedback is invaluable as we build a better GitHub experience for all our users. Here's what you can expect moving forward ⏩
Where to look to see what's shipping 👀
What you can do in the meantime 💻
As a member of the GitHub community, your participation is essential. While we can't promise that every suggestion will be implemented, we want to emphasize that your feedback is instrumental in guiding our decisions and priorities. Thank you once again for your contribution to making GitHub even better! We're grateful for your ongoing support and collaboration in shaping the future of our platform. ⭐ |
|
You’re hitting npm’s typosquatting / similarity gate. It’s enforced only on the registry’s
What the rule roughly isnpm compares a normalized form of the name (strip hyphens/underscores/dots, case-fold) against existing unscoped names. This is intentional anti-typosquat policy, not a docs bug in What you can do today
Feature ask (reasonable)A preflight like So: your tooling didn’t lie — the similarity check simply isn’t in the client path yet. Scoped publish is the reliable workaround. |
Uh oh!
There was an error while loading. Please reload this page.
🏷️ Discussion Type
Bug
Body
"Package name too similar to existing package": the actual rule is not documented and cannot be checked before publish
What happened
I took a package to the point of release under the name
md-render: repository, README, badges, CI, docs, a git tag, GitHub topics, an ESM/CJS build.npm publishfailed at the last step:The package that blocks it,
mdrender, published its last release (1.0.2) in July 2013, and its description on the registry readsERROR: No README.md file found!.Nothing npm provides on the way to publish warns about this:
npm view md-rendernpmjs.com/package/md-rendernpm publish --dry-run+ md-render@9.9.9: the check is server sidevalidate-npm-package-name, npm's own validatorThird-party tooling inherits the blindness:
can-npm-publishexits 0 too. The one tool that does flag the name, npm-name (about 150k weekly downloads), can do so only because the rule was reverse-engineered into it from the 2018 blog post quoted below, and the reverse-engineered version is incomplete.So the check that decides the outcome runs after every other decision has been made and written down: the repository name, the package name in every code example, import paths, badge URLs, CI config, git tags, and the install line other people may already have copied. In my case the recovery meant renaming the package, the GitHub repository, the tag, and every reference in docs and CI; it now ships as
prompt-render.The rule is documented ambiguously, and the natural reading is wrong
The package name guidelines require that an unscoped name "is not spelled in a similar way to another package name", and never define similar. The closest thing to a definition is the 2018 moniker rules post:
The first sentence removes punctuation from one name only: the new one. Whether existing names are also normalised is left to the reader, and npm-name implemented the one-sided reading.
That reading is wrong. I tested the registry with a throwaway pair of names; the one that published has since been unpublished:
bug3.preflight-probe.bug3-preflight-probewhile the first was live:The existing punctuated name blocked the new one, so both sides are normalised. This is not a corner case: it means
lodash-mergeis unpublishable becauselodash.mergeexists, and nothing documents that. Learning it required publishing a package to the public registry, because there is no other way to observe the rule.And punctuation is not even the whole rule. A 2024 report shows the registry blocking
noxeas too similar tonode, which no punctuation stripping explains. Whatever check did that appears in no documentation at all.What I am asking for
Not the removal of the rule. Typosquat prevention is worth having. In ascending order of cost:
noxe.mdrender."npm publish --dry-run, so the failure happens before the release, not during it.Why tooling cannot close this gap alone
The likely collisions are cheap to find from outside. Checking the spellings that share the candidate's own word boundaries is four requests, and finds
mdrenderin under a second:I have sent that check to npm-name.
A complete check is impossible from outside. Any existing name whose stripped form matches can block, and for a name with no punctuation the cheap check has nothing to vary:
lodashmergeis blocked bylodash.merge, and finding that means trying every way to re-insert separators, which is 4^(n-1) spellings, about a million for an 11-character name. The registry has no endpoint that answers which existing names strip down to a given string, and the search API is not a substitute: it happens to surfacelodash.mergeforlodashmerge, but a search forsocketiodoes not returnsocket.io. Only the registry can answer "can this name be published", which is why item 4 is the only complete fix.A note on the rule's reach
A package whose last release is thirteen years old and whose registry description is an error string blocks an entire family of names, and the error message offers only a scope as a way out. That is by policy: the disputes policy states that "npm does not resolve squatting claims on demand", and the only documented path is trademark-based. If the similarity rule keeps this reach, a documented path for releasing long-abandoned names would help.
Prior art
npm publishrejects. It was closed within minutes, and a punctuation check only reached npm-name in 2026, reverse-engineered from the blog post.The gap was reported eight years ago. It is still the first wall a new publisher hits, and the documentation still does not say how the rule actually works.
All reactions