Fix it fast
Most likely: Cargo is using the right command but cannot retrieve a token for the registry that command selected.
Confirm this is your error
Match the output and confirm you are troubleshooting the same failure.
error: no token found, please run `cargo login`
error: no token found, please run `cargo login` or use environment variable CARGO_REGISTRY_TOKEN Check the cause
Run focused checks to identify what is failing in this environment.
cargo -Vv
grep -nE "default|credential-provider|global-credential-providers" .cargo/config.toml "${CARGO_HOME:-$HOME/.cargo}/config.toml" 2>/dev/null
test -n "$CARGO_REGISTRY_TOKEN" && echo "crates.io token is set" || echo "crates.io token is missing" Apply the safe fix
Use the smallest safe change that addresses the confirmed cause.
# Developer machine
cargo login --registry <name>
# CI: inject the registry secret as CARGO_REGISTRIES_<NAME>_TOKEN without printing it. Verify it works
Repeat the relevant checks and confirm the original error is gone.
cargo owner --registry <name> --list <known-owned-crate>
# When the release is ready, rerun the original authenticated command once. Avoid unsafe shortcuts
Keep security and data protections in place while troubleshooting.
- Do not paste tokens into command output, issue reports, or committed config files.
- Do not reuse a crates.io token for a private registry or silently change the release target.
What Access Failed
This is usually a target-and-identity problem, not a syntax problem. The request made it to the server, but the server did not like the credentials, permissions, or repository path attached to it.
Fix credentials and target access
Check the target and the credential together. Most of these fixes come down to using the right URL, account or token, and scope or repository permissions in the environment that actually failed.
Missing local credential:run cargo login --registry <name> and let the configured provider store the token. Prefer an OS-backed provider when your environment supports one.
Missing CI credential:inject the registry-specific secret into the failing job and map it to CARGO_REGISTRIES_<NAME>_TOKEN without printing it.
Wrong target:pass --registry <name> explicitly or correct registry.default so the command and token refer to the same registry.
Provider mismatch:configure the provider recommended by the private registry, or include cargo:token as a deliberate fallback when environment-token lookup is required.
Container mismatch:mount only the necessary Cargo config and use job-scoped secrets instead of copying a developer credentials file into an image.
Check the target registry and credential provider
Record the exact client and host context with cargo -Vv and confirm that the failing shell is the same environment that receives the registry secret.
Check the selected target without printing secrets:inspect registry.default, the command --registry flag, and the matching [registries.<name>] entry in Cargo config.
Confirm that registry.global-credential-providers or registries.<name>.credential-provider includes the provider your team expects.
In CI, verify that CARGO_REGISTRY_TOKEN or CARGO_REGISTRIES_<NAME>_TOKEN is present by checking only whether it is set. Never echo the value into logs.
Why It Happens
The developer has not logged in to the selected registry, or the CI secret was not injected into this job.
Cargo is targeting crates.io while the available token belongs to a private registry, or the reverse.
The token variable is correctly named but cargo:token is missing from the active provider chain.
A container or runner uses a different CARGO_HOME, so it cannot see the credentials or config available on the host.
Prove the Failing Environment Can Reach It
Re-run the original publish, owner, or yank command in the same shell or CI runner. Cargo should advance past credential retrieval into packaging or registry API work.
If the next message is a publish-policy, permission, or duplicate-version error, authentication is now working and the failure has moved to a later layer.
How Cargo chooses a registry credential
This is the part worth understanding if the quick fix did not hold. It explains what Cargo is trying to do at the moment the error appears.
Cargo resolves the registry named by --registry, registry.default, or the command default before asking its configured credential providers for a token.
The failure happens before upload or ownership changes. A working token for another registry does not satisfy the selected target, and token environment variables only work when the cargo:token provider is active.
Keep Credentials and Targets Aligned
To prevent this, give each registry one canonical config name and one documented CI secret name so credentials cannot be applied to the wrong target, pin the credential-provider configuration in developer bootstrap and runner images, while keeping actual tokens out of repositories and container layers, and run a redacted registry-auth preflight before release jobs so missing secrets fail before packaging starts.
Docs and source code
Cargo Registry Authentication
Official Cargo guidance for credential providers, token lookup, and private registry authentication. - Source
Cargo authenticates to registries with credential providers. Cargo Registries
Official configuration and publishing behavior for crates.io and alternative registries. - Source
Cargo installs crates and fetches dependencies from a registry. 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 owner
Official authenticated registry command for listing crate owners without changing them. - Source
The --list option lists owners of a crate.