Publish safely

Recover from a bad release

Use deprecation, a fixed follow-up version, dist-tags, and clear communication instead of rewriting history.

Published npm versions are normally immutable. You cannot overwrite @acme/[email protected] in place. Recovery means steering consumers toward a known-good release.

Imagine 1.2.0 shipped with a regression: empty strings throw instead of returning ''. Downloads are already happening. Here is the sequence I follow.

1. Stop promotion

Do not move dist-tags forward. If latest already points at the bad version, plan a fix before you touch tags again.

2. Deprecate with a precise message

npm deprecate @acme/[email protected] "Broken empty-string handling. Upgrade to >=1.2.1"

Consumers who install fresh see the warning during npm install. Existing lockfiles still resolve until they upgrade.

3. Ship a tested fix as a new version

Fix the bug, run the full release gate, bump the patch version, and publish:

npm version patch
npm publish --access public

4. Move latest only after verification

npm dist-tag add @acme/[email protected] latest
npm dist-tag ls @acme/slugify-title

Output should show latest: 1.2.1.

5. Tell affected users

Post a short note: affected range, symptom, fixed version, and workaround if they cannot upgrade immediately.

What not to do

Do not reuse the same version number. Do not silently retag latest without a fixed release. Unpublish is limited to very new packages with almost no downloads and creates broken installs for anyone who cached the tarball.

Write the recovery timeline before you need it. When something breaks at midnight, a checklist beats improvisation.

If only latest was affected and older versions are fine, say so in the deprecation message. Pinning consumers on 1.1.x should not look like a crisis when 1.1.9 still works.

After recovery, add a release-gate test that would have caught the bug. A missing consumer smoke case is often the real root cause, not npm itself.

Lesson completed