Skip to content
Latchkey

NuGet restore 401/403 - Authenticate to a Private Feed in CI

NuGet reached a private feed but had no valid credentials, so the feed returned 401 (Unauthorized) or 403 (Forbidden). Restore needs an authenticated source for internal packages.

What this error means

Restore fails on a private source with a 401 or 403 status code. It is deterministic. The same job fails the same way every run until credentials are supplied, unlike a transient network failure.

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

Common causes

No credentials configured for the feed

The private source has no username/password (PAT) or token wired up in NuGet.config or the environment, so NuGet falls back to anonymous and is rejected.

Expired or wrong-scope token

A personal access token or feed key expired, or it lacks Packaging (read) scope. Azure Artifacts and GitHub Packages both reject under-scoped tokens with 401/403.

How to fix it

Add the authenticated source with a token

Register the feed with credentials, storing the token in a CI secret rather than in the repo.

Terminal
dotnet nuget add source \
  https://pkgs.dev.azure.com/contoso/_packaging/internal/nuget/v3/index.json \
  --name internal --username unused \
  --password "$NUGET_TOKEN" --store-password-in-clear-text

Use environment-variable credentials in NuGet.config

Reference a secret via %ENV% so the token never lands in source control.

NuGet.config
<packageSourceCredentials>
  <internal>
    <add key="Username" value="unused" />
    <add key="ClearTextPassword" value="%NUGET_TOKEN%" />
  </internal>
</packageSourceCredentials>

For Azure Artifacts, use the credential provider

  1. Set VSS_NUGET_EXTERNAL_FEED_ENDPOINTS with the feed URL and a PAT.
  2. Install the artifacts credential provider so dotnet restore picks it up automatically.
  3. Grant the PAT the Packaging (read) scope, and rotate it before it expires.

How to prevent it

  • Store feed tokens as CI secrets and inject them via environment variables.
  • Use a least-privilege token scoped to Packaging read, and track its expiry.
  • Keep credentials out of committed NuGet.config files.

Frequently asked questions

What causes ""401 (Unauthorized)" on restore"?
The private source has no username/password (PAT) or token wired up in NuGet.config or the environment, so NuGet falls back to anonymous and is rejected.
How do I fix "401 (Unauthorized)" on restore?
Register the feed with credentials, storing the token in a CI secret rather than in the repo.

Related guides

References

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