Skip to content

Commit cc0c047

Browse files
jcansdaleCopilotjc-clark
authored
Add packageSourceMapping troubleshooting for NuGet registry (#59792)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Joe Clark <31087804+jc-clark@users.noreply.github.com>
1 parent 6d1e479 commit cc0c047

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

content/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,61 @@ If you're using a nuspec file, ensure that it has a `repository` element with th
296296

297297
If you're using a `GITHUB_TOKEN` to authenticate to a {% data variables.product.prodname_registry %} registry within a {% data variables.product.prodname_actions %} workflow, the token cannot access private repository-based packages in a different repository other than where the workflow is running in. To access packages associated with other repositories, instead generate a {% data variables.product.pat_v1 %} with the `read:packages` scope and pass this token in as a secret.
298298

299+
### Intermittent 403 errors when restoring public packages
300+
301+
If you're using {% data variables.product.prodname_registry %} alongside _nuget.org_ and experiencing intermittent 403 Forbidden errors when restoring standard public packages (like `Microsoft.Extensions.*`), this may occur because NuGet queries all configured package sources for every package. If {% data variables.product.prodname_registry %} authentication fails temporarily, it can block the entire restore—even for packages that don't exist on {% data variables.product.prodname_registry %}.
302+
303+
To avoid this, use [NuGet Package Source Mapping](https://learn.microsoft.com/nuget/consume-packages/package-source-mapping) to route packages to specific sources.
304+
305+
Replace:
306+
* `NAMESPACE` with the name of the personal account or organization that owns your {% data variables.product.prodname_registry %} NuGet feed.
307+
* `PACKAGE-ID-PREFIX` with the NuGet package ID prefix that you use for packages hosted on {% data variables.product.prodname_registry %}. If you use multiple prefixes, add additional `<package>` entries for each prefix.{% ifversion ghes %}
308+
* `HOSTNAME` with the host name for {% data variables.location.product_location %}.{% endif %}
309+
310+
{% ifversion ghes %}If your instance has subdomain isolation enabled:
311+
{% endif %}
312+
313+
```xml
314+
<configuration>
315+
<packageSources>
316+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
317+
<add key="github" value="https://{% ifversion fpt or ghec %}nuget.pkg.github.com{% else %}nuget.HOSTNAME{% endif %}/NAMESPACE/index.json" />
318+
</packageSources>
319+
<packageSourceMapping>
320+
<packageSource key="nuget.org">
321+
<package pattern="*" />
322+
</packageSource>
323+
<packageSource key="github">
324+
<package pattern="PACKAGE-ID-PREFIX.*" />
325+
</packageSource>
326+
</packageSourceMapping>
327+
</configuration>
328+
```
329+
330+
{% ifversion ghes %}
331+
If your instance has subdomain isolation disabled:
332+
333+
```xml
334+
<configuration>
335+
<packageSources>
336+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
337+
<add key="github" value="https://HOSTNAME/_registry/nuget/NAMESPACE/index.json" />
338+
</packageSources>
339+
<packageSourceMapping>
340+
<packageSource key="nuget.org">
341+
<package pattern="*" />
342+
</packageSource>
343+
<packageSource key="github">
344+
<package pattern="PACKAGE-ID-PREFIX.*" />
345+
</packageSource>
346+
</packageSourceMapping>
347+
</configuration>
348+
```
349+
350+
{% endif %}
351+
352+
NuGet uses the [most specific matching pattern](https://learn.microsoft.com/nuget/consume-packages/package-source-mapping#package-pattern-precedence), so packages matching `PACKAGE-ID-PREFIX.*` are fetched only from {% data variables.product.prodname_registry %}, while all other packages are fetched from _nuget.org_. This also helps prevent dependency confusion attacks by ensuring your private packages can only come from your {% data variables.product.prodname_registry %} feed.
353+
299354
## Further reading
300355

301356
* [AUTOTITLE](/packages/learn-github-packages/deleting-and-restoring-a-package)

0 commit comments

Comments
 (0)