Skip to content
Latchkey

dotnet nuget push "401 Unauthorized" (API key) in CI

The feed rejected the push because the API key was absent, invalid, or expired. nuget.org authenticates pushes with an API key passed via --api-key; private feeds may need credentials configured on the source instead.

What this error means

dotnet nuget push fails with "Response status code does not indicate success: 401 (Unauthorized)." or "The specified API key is invalid, has expired, or does not have permission to access the specified package."

nuget
Pushing MyLib.1.2.1.nupkg to 'https://api.nuget.org/v3/index.json'...
error: Response status code does not indicate success: 401 (Unauthorized).
error: The specified API key is invalid, has expired, or does not have permission.

Common causes

No or wrong API key for nuget.org

The push sent no --api-key, or one that is expired or scoped to a different package glob, so the feed returns 401.

A private feed needing source credentials

Some feeds (GitHub Packages, Azure Artifacts) authenticate via a configured source with username and password, not a bare --api-key.

How to fix it

Pass a valid API key from a secret

Supply the API key on the push command, sourced from a CI secret.

.github/workflows/release.yml
dotnet nuget push "**/*.nupkg" \
  --api-key "${{ secrets.NUGET_API_KEY }}" \
  --source https://api.nuget.org/v3/index.json

Configure credentials for a private source

For feeds that use source auth, add the source with credentials before pushing.

Terminal
dotnet nuget add source https://nuget.pkg.github.com/OWNER/index.json \
  --name github --username OWNER --password "$GITHUB_TOKEN" --store-password-in-clear-text

How to prevent it

  • Store the NuGet API key as a CI secret and pass it via --api-key.
  • Scope the API key to the package glob you publish.
  • For private feeds, configure source credentials rather than an API key.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →