Fix it fast
Most likely: An earlier job already published the version, or the release forgot to increment it.
Confirm this is your error
Match the output and confirm you are troubleshooting the same failure.
error: crate example-cli@1.4.0 already exists on crates.io index
error: crate internal-api@2.7.1 already exists on registry index Check the cause
Run focused checks to identify what is failing in this environment.
grep -n "^name =|^version =" Cargo.toml
# Run outside a workspace if you do not want Cargo to create Cargo.lock.
cargo info --registry <name> <crate>@<version> Apply the safe fix
Use the smallest safe change that addresses the confirmed cause.
# If this is new release content, bump the version in Cargo.toml.
# If the version already represents this commit, do not publish it again. Verify it works
Repeat the relevant checks and confirm the original error is gone.
cargo info --registry <name> <crate>@<version> Avoid unsafe shortcuts
Keep security and data protections in place while troubleshooting.
- Do not loop
cargo publishafter an ambiguous timeout. - Do not rewrite source tags to pretend an existing registry artifact came from another commit.
What This Error Means
Read this as a precise clue about which part of the workflow broke first. Once you know the failing layer, the fix path gets much shorter.
How to Fix It
The fastest fixes here come from checking the immediate failing layer before you change anything unrelated. Make one correction at a time and re-test from the same environment.
Earlier publish succeeded:do not republish. Continue only the safe downstream release steps after verifying the existing artifact.
New code needs release:increment the crate version according to the project versioning policy, regenerate dependent lockfiles if needed, and publish the new version.
Wrong workspace package:correct the package selection and verify its manifest before another upload.
Concurrent jobs:serialize publishing per crate or use a release lock so only one job can own a version.
Private-index delay:poll for the version after upload and make retries check registry state before calling cargo publish again.
Why It Happens
A previous publish completed, but the job was retried after a later step failed or timed out.
Release automation reused an existing version because the manifest bump was missed or the wrong workspace member was selected.
Two concurrent jobs attempted to publish the same crate version.
A private registry accepted the upload but exposed the index entry after a delay, causing an unsafe retry.
Verify the Fix
Confirm the intended version is visible and downloadable from the same registry used by consumers.
For a new version, run cargo publish --dry-run --registry <name> first, then publish once and verify the resulting index entry before downstream jobs continue.
Check whether the earlier publish succeeded
Read package.name and package.version from the selected manifest and confirm the release job is publishing the intended workspace member.
Check the target registry UI or API for that exact name and version before rerunning any publish step.
Inspect prior CI job logs for upload completion, registry acceptance, or a timeout while waiting for the new index entry to appear.
Compare the source tag and commit attached to the existing registry version with the current release checkout.
How registries enforce unique crate versions
A registry version is identified by crate name and version. Publishing is append-only in normal Cargo workflows, so a retry cannot overwrite the bytes or metadata of an existing release. The most important incident question is whether an earlier job already completed the upload before timing out or failing in a later notification, tag, or index-polling step.
Prevent It From Coming Back
To prevent this, make release jobs idempotent by checking registry state before publish and after any ambiguous timeout, allow only one publishing job per crate and version, and record the source commit and registry version together so reruns can distinguish completed releases from failed attempts.
Docs and source code
cargo publish
Official publish stages, dry-run behavior, registry selection, and authentication requirements. - Source
This command will create a distributable, compressed crate file and upload it to a registry. cargo info
Official command for inspecting one exact package version from a selected registry. - Source
This command displays information about a package. Cargo Registry Web API
Official API contract for publishing crates and returning registry errors. - Source
Cargo includes the Authorization header for requests that require authentication.