dependabot / dependabot/dependabot-core
nuget: >2 TargetFrameworks routes into a restore mode that hard-crashes on a known NuGet NRE
- Dominant language
- Ruby
- Stars
- 5.8k
- Forks
- 1.5k
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 149
Description
## Summary
`SdkProjectDiscovery.DiscoverAsync` routes any project reporting more than `MaximumParallelTargetFrameworkRestores` (2) target frameworks into an "individual TFM restore" mode. That mode invokes restore with `/p:TargetFramework={tfm}` set explicitly, once per framework:
https://github.com/dependabot/dependabot-core/blob/main/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs
Passing an explicit `TargetFramework` property to a restore using static graph evaluation trips a long-standing NuGet bug: [NuGet/Home#11761](https://github.com/NuGet/Home/issues/11761), open since 2022, an NRE in `MSBuildStaticGraphRestore`. The crash is triggered purely by the explicit property. It reproduces identically on a plain single-target project given the same override, with no multi-targeting involved at all.
## Repro
Any project with 3+ `TargetFrameworks` and central package management (`Directory.Packages.props`) hits this on every Dependabot nuget job. Reproduced independent of Dependabot with a plain SDK-style project:
```
dotnet restore SomeProject.csproj -p:TargetFramework=net10.0
```
This crashes with the identical stack trace dependabot-core's nuget jobs report:
```
NuGet.RestoreEx.targets(19,5): error : Object reference not set to an instance of an object.
at NuGet.Build.Tasks.Console.MSBuildStaticGraphRestore...
```
## Impact
Every nuget update job for a repo with a 3+-TFM project effectively never completes discovery. It burns through this crash repeatedly (each hit logs a WARN and continues) across every project that references the multi-targeted one, until GitHub Actions kills the job on timeout. In our case that's ~55 minutes per run with no successful completion.
## Possible fix direction
`dotnet build --framework {tfm}` is the SDK's documented, supported entry point for pinning one TFM of a multi-targeted project. It dispatches through the SDK's supported inner/outer-build machinery and does not reproduce the crash (confirmed locally). Worth considering for the individual-TFM restore path, if the discovery step can tolerate the fuller build it triggers.
Contributor guide
Research direction
Start in NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs, especially the individual-TFM restore path selected above two target frameworks. Reproduce the failure with `dotnet restore SomeProject.csproj -p:TargetFramework=net10.0` and compare it with the documented `dotnet build --framework {tfm}` entry point. Done means discovery no longer repeatedly hard-crashes on multi-targeted projects and can complete its restore work.
Written by the indexing model from the issue text.
Assessment
- Domain
- build-system, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100