Safeguard
Developer Tools•

Why can't you change a tagged Go module version after publishing it?

Go tools check a module against the first copy they downloaded. If a tag later points elsewhere, users get a security error. Publish a new version.

Safeguard Security Team
4 min read

Because Go tools authenticate a downloaded module against the first copy they saw. If the code behind a tag changes, the new download no longer matches and Go reports a security error. The fix is always the same: publish a new version rather than altering the old one.

What the Go documentation says

The Go page on publishing a module carries a plain note: do not change a tagged version of a module after publishing it. For developers using the module, Go tools authenticate a downloaded module against the first downloaded copy. If the two differ, the tools return a security error. Instead of changing the code for a previously published version, publish a new version.

The publishing steps on the same page are short: tidy the module's dependencies, run the tests a final time, tag the project with a new version number using git, push the tag, then run a list command so Go updates its index of modules.

What this protects

The design means a version number is a promise. Once your users, and the Go tooling around them, have seen v1.2.3, it should refer to the same bytes forever. That protects them from a tag being quietly repointed, by an attacker or by an honest maintainer who wanted to sneak in a late fix.

It also means a mistake in a published version is permanent in one sense: you cannot take it back by retagging.

What to do when you tagged the wrong thing

SituationAction
Tagged locally, not pushedDelete or recreate the tag freely
Pushed but nobody could have used itStill safer to use a new version number
Released with a bugFix and tag the next patch version
Released with a serious problemNext version plus a retraction, see below

Our post on what happens when a git tag moves after you pulled it explains the general problem that Go's design guards against.

Retraction as a signal

The Go modules reference describes a retract directive in go.mod. It indicates that a version or range of versions should not be depended upon, and is useful when a version was published prematurely or a severe problem was found after publication. Retracted versions remain available in version control and on module proxies so that builds depending on them do not break. Each directive should carry a comment explaining why, and the go command may show that comment in warnings and list output.

You publish a retraction by releasing a new version whose go.mod contains the directive. See what Go retract does for consumers for the other side of this.

// Published by mistake, contains a debug backdoor flag.
retract v1.2.3

A release routine that fits

  1. Tidy and test on the release commit.
  2. Tag with a semantic version and push the tag.
  3. Request the listing so the module index updates.
  4. If something is wrong, tag the next version. Add a retraction when the old one should not be used.

Quick check

Can I delete a bad Go tag to hide it?

Deleting the tag in your repository does not undo what proxies and users already fetched. Use a new version and, where fitting, a retraction.

Does a retraction remove the version?

No. The documentation says retracted versions remain available so builds are not broken. It is a warning, not a deletion.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.