Back to publishing & release Automate semantic versioning Publish to the npm registry Harden the supply chain

Fixing npm 'Cannot Publish Over Previously Published Version'

npm publish fails because the version already exists on the registry — npm forbids overwriting a published version. This page explains why immutability matters and how to publish correctly.

Exact symptoms and error messages

Exact symptoms and error messages Exact symptoms and error messages in production JavaScript package workflows. Exact symptoms and error messages Exact symptoms and error messages in production JavaScript package workflows.
Exact symptoms and error messages — the core idea of this section at a glance.
npm error code E403
npm error 403 Forbidden - PUT https://registry.npmjs.org/@acme%2fui
npm error You cannot publish over the previously published versions: 2.3.0.

Root cause analysis

Published versions are immutable by design: consumers and lockfiles pin exact versions, so allowing an overwrite would let a version's contents change under everyone who already installed it. The error means your package.json version was not bumped since the last publish. The fix is a new version, chosen by the semantic versioning rules, published through the lifecycle in npm Registry Publishing Workflows.

Root cause analysis Published versions are immutable by design: consumers and lockfiles pin exact versions, so allowing an overwrite would l Root cause analysis Published versions are immutable by design: consumers and lockfiles pin exact versions, so allowing an overwrite would let a version's contents change under eve
Root cause analysis — the core idea of this section at a glance.

Published versions are immutable by design, and that immutability is a feature, not a limitation. Consumers pin exact versions in their lockfiles, and integrity hashes verify that the tarball for a version never changes. If the registry allowed republishing different contents under the same version, every install that had already resolved it would silently get different code — the exact reproducibility guarantee the whole system depends on. The 403 is the registry protecting that guarantee.

The error therefore means one concrete thing: your package.json version was not bumped since the last publish. The fix is never to force an overwrite — there is no such operation — but to choose a new version. Which part to bump follows from the change, per the semantic versioning rules: a fix is a patch, a compatible feature is a minor, a breaking change is a major.

Resolution and configuration patch

Bump to an unused version before publishing:

Resolution and configuration patch Bump to an unused version before publishing: Resolution and configuration patch Bump to an unused version before publishing:
Resolution and configuration patch — the core idea of this section at a glance.
# choose the bump that matches the change
npm version patch   # or minor / major
npm publish

If you must ship a fix to an already-published version, publish a new patch and, if the bad version is dangerous, deprecate it — you cannot overwrite it.

CLI validation and debug commands

CLI validation and debug commands CLI validation and debug commands in production JavaScript package workflows. CLI validation and debug commands CLI validation and debug commands in production JavaScript package workflows.
CLI validation and debug commands — the core idea of this section at a glance.
# See which versions already exist
npm view @acme/ui versions --json
# Confirm your local version is unused
npm view @acme/ui@$(node -p "require('./package.json').version") 2>&1 | grep -q 'code E404' && echo 'free' || echo 'taken'

Prevention and CI guardrails

  • Automate version bumping so a publish never reuses a version.
  • Gate CI publishing on a changed version to fail fast on duplicates.
  • Deprecate a bad version (npm deprecate) instead of trying to overwrite it.
  • Use prerelease tags for iterative testing so you do not burn stable versions.
Prevention and CI guardrails Prevention and CI guardrails in production JavaScript package workflows. Prevention and CI guardrails Prevention and CI guardrails in production JavaScript package workflows.
Prevention and CI guardrails — the core idea of this section at a glance.

Automating version bumps so this never recurs

The durable fix is to remove the manual step where a version can be forgotten. When versioning is derived automatically — from conventional commits or changeset intent files — a publish can never reuse a version, because the version is computed from the changes rather than typed by hand.

Automated bump Compute the version from changes so it never repeats. changeset / commits record intent compute next version never reused publish new version guaranteed
Deriving the version from changes makes a duplicate publish structurally impossible.
- run: npx changeset version   # computes the next version from intent files
- run: npm publish

With Changesets or semantic-release driving the bump, the release pipeline reads the accumulated changes, calculates the correct next version, updates package.json, and publishes — with no opportunity for a human to publish twice from the same version. This turns 'cannot publish over existing version' from a recurring papercut into a class of error the pipeline makes structurally impossible, which is the point of automating the release.

Recovering from a bad published version

Because you cannot overwrite a version, recovering from a broken release means shipping a new one and steering consumers away from the old. Publish a fixed higher version immediately, then deprecate the broken one with a message that points at the fix.

Recovery flow Ship a patch, then deprecate the broken version. publish patch fixed version npm deprecate old warn installers consumers upgrade guided to fix
You cannot overwrite — ship a fix and deprecate the bad version instead.
# Ship the fix as a new version
npm version patch && npm publish
# Warn anyone installing the broken version
npm deprecate your-pkg@2.3.0 "Broken release — upgrade to 2.3.1"

npm deprecate does not remove the version — consumers who pinned it still resolve it — but it surfaces a warning on install that guides them to the fixed release. For a genuinely dangerous version there is a narrow, time-limited npm unpublish window with restrictions, but deprecation plus a prompt patch is the standard, non-disruptive recovery that respects the immutability every consumer relies on.

Frequently Asked Questions

Can I ever overwrite a published version?

No. Published versions are immutable. You can npm deprecate or, within a short window and with restrictions, npm unpublish, but you cannot republish different contents under the same version.

What if I published a broken version?

Publish a fixed higher version immediately, then deprecate the broken one with a message pointing to the fix so installers are warned.

Can I ever overwrite a published version?

No — published versions are immutable so that lockfiles and integrity hashes stay valid. You can deprecate a version or, within a narrow window, unpublish it, but you cannot republish different contents under the same version number.

How do I stop reusing a version by accident?

Automate the bump. With Changesets or semantic-release, the next version is computed from the changes, so a publish can never reuse a version — the manual step where it could be forgotten is removed.

What do I do about a broken release I already published?

Publish a fixed higher version immediately, then npm deprecate the broken one with a message pointing at the fix. Deprecation warns installers without removing the version, respecting the immutability consumers depend on.

Related

npm Registry Publishing Workflows