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.
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.
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-textUse environment-variable credentials in NuGet.config
Reference a secret via %ENV% so the token never lands in source control.
<packageSourceCredentials>
<internal>
<add key="Username" value="unused" />
<add key="ClearTextPassword" value="%NUGET_TOKEN%" />
</internal>
</packageSourceCredentials>For Azure Artifacts, use the credential provider
- Set
VSS_NUGET_EXTERNAL_FEED_ENDPOINTSwith the feed URL and a PAT. - Install the artifacts credential provider so
dotnet restorepicks it up automatically. - 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.