Skip to content
Latchkey

dotnet restore 401 (Unauthorized) from a private feed in CI

The private feed answered but rejected the request with 401: no credentials were sent, or the token was expired or malformed. The feed is reachable; authentication is the problem.

What this error means

restore fails on the private source with "Response status code does not indicate success: 401 (Unauthorized)" while public nuget.org packages restore fine.

dotnet
error NU1301: Unable to load the service index for source https://pkgs.dev.azure.com/org/_packaging/feed/nuget/v3/index.json.
      Response status code does not indicate success: 401 (Unauthorized).

Common causes

No credentials reached the restore step

The feed needs a PAT or token, but the secret was never injected, or nuget.config has no credentials for that source, so restore sends an anonymous request.

The token or PAT expired

A previously working PAT lapsed. Azure Artifacts and GitHub Packages tokens have expiries; once past, every restore returns 401.

How to fix it

Inject a valid PAT via a secret

  1. Store the feed PAT as a repository or organization secret.
  2. Add a credentialed source or set the feed username/password from the secret.
  3. Re-run restore; a valid token turns the 401 into a successful index load.
.github/workflows/ci.yml
- run: dotnet nuget add source https://pkgs.dev.azure.com/org/_packaging/feed/nuget/v3/index.json \
    --name private --username az --password ${{ secrets.AZ_ARTIFACTS_PAT }} --store-password-in-clear-text

Rotate an expired PAT

Issue a fresh token with Packaging read scope and update the secret in one place; a 401 from expiry clears once the new token is used.

How to prevent it

  • Store feed PATs as CI secrets, never in a committed nuget.config.
  • Track PAT expiry and rotate before it lapses.
  • Grant least-privilege read scope to the feed for the restore token.

Frequently asked questions

What causes ""401 (Unauthorized)""?
The feed needs a PAT or token, but the secret was never injected, or nuget.config has no credentials for that source, so restore sends an anonymous request.
How do I fix "401 (Unauthorized)"?
Inject a valid PAT via a secret

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card