NuGet Private Feed PAT Expired - Restore Stops Authenticating
A private-feed restore that worked for weeks suddenly fails with 401 because the personal access token behind it expired. Nothing in the project changed - the credential simply lapsed and must be rotated.
What this error means
Restore that previously succeeded now fails with a 401 on the private feed, and the change correlates with a PAT expiry date rather than any code change. Re-issuing the token and re-injecting it restores success.
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
The feed PAT reached its expiry date
Azure Artifacts and other feeds issue PATs with a finite lifetime. Once the date passes, the token is rejected with 401 even though it was valid the day before.
A rotated token was not re-injected into CI
The token was rotated in the feed but the CI secret still holds the old value, so restore keeps presenting the dead credential.
How to fix it
Issue a fresh PAT and update the CI secret
Re-create the token with Packaging (read) scope and store it in the CI secret the workflow injects.
# after updating the secret, the workflow injects it:
dotnet nuget update source internal \
--username unused --password "$NUGET_TOKEN" \
--store-password-in-clear-textTrack expiry so it does not lapse silently
- Set a calendar reminder before the PAT expiry, or use a short rotation cadence.
- Prefer workload identity / OIDC where the feed supports it, so there is no long-lived PAT.
- After rotation, run restore once to confirm the new token authenticates.
How to prevent it
- Track PAT expiry dates and rotate before they lapse.
- Prefer OIDC/workload-identity feed auth over long-lived PATs where available.
- Store tokens in CI secrets and inject via environment variables only.