NuGet restore Timeouts - Fix Slow or Hanging Feeds in CI
A restore request to the feed stalled past NuGet’s timeout and was canceled. These are transient network or feed-slowness failures that usually pass on retry.
What this error means
Restore hangs and then fails with a timeout or "The operation was canceled", often partway through downloading packages. Re-running the job frequently succeeds with no change.
error : The operation was canceled.
error : Unable to load the service index for source https://api.nuget.org/v3/index.json.
The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.Common causes
Slow or overloaded feed
A busy public feed or an under-provisioned internal feed serves packages slowly enough to exceed the request timeout.
Large package graph over a congested link
Restoring many packages (or large native assets) on a slow runner network can blow past the default timeout before everything downloads.
How to fix it
Raise the timeout and retry count
Give NuGet more time per request and more attempts for transient blips.
# raise per-request timeout (seconds) and retries
dotnet restore --verbosity normal
export NUGET_HTTP_REQUEST_TIMEOUT=300
# or in NuGet.config: <config><add key="http_request_timeout" value="300" /></config>Cache the global packages folder
Caching ~/.nuget/packages between runs means most packages are already local, so feed slowness matters far less.
- uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: nuget-${{ hashFiles('**/packages.lock.json') }}Use a closer or internal feed
- Point restore at a geographically closer mirror or pull-through cache.
- Host an internal feed (Azure Artifacts upstream, BaGet) for high-volume pipelines.
- Commit a lock file so the restore set is stable and cacheable.
How to prevent it
- Cache the NuGet global packages folder keyed on the lock file.
- Enable a locked restore (
packages.lock.json) so downloads are deterministic. - Use an internal feed/upstream to reduce dependence on public nuget.org.