Skip to content

validate -mt works with static graph restore #13153

@JanProvaznik

Description

@JanProvaznik

Investigation Results: -mt mode breaks NuGet static graph restore for conditional ProjectReferences

Summary

When MSBuild runs with -mt (multithreaded) mode AND RestoreUseStaticGraphEvaluation=true, conditional ProjectReference items that depend on MSBuildRestoreSessionId are not properly evaluated during graph construction, causing those projects to be excluded from restore.

Reproduction

Environment: dotnet/runtime repo with RestoreUseStaticGraphEvaluation=true (default)

Problematic pattern in src/libraries/pretest.proj:

<ExternalsProject Include="externals.csproj" ... />
<ProjectReference Include="@(ExternalsProject)" Condition="'$(MSBuildRestoreSessionId)' != ''" />

This pattern is intended to include externals.csproj as a ProjectReference only during restore (when MSBuildRestoreSessionId is set).

Test Results

Test -mt mode Static Graph Restore externals.csproj Restored NETSDK1004 Error
1 ✅ Yes ✅ Yes No Yes (BUG)
2 ✅ Yes ❌ No ✅ Yes ❌ No
3 ❌ No ✅ Yes ✅ Yes ❌ No

Commands Used

# Test 1: FAILS - externals.csproj not restored
dotnet msbuild Build.proj -restore -t:Build -p:Subset=libs.pretest -p:Configuration=Release -mt -m

# Test 2: WORKS - externals.csproj restored
dotnet msbuild Build.proj -restore -t:Build -p:Subset=libs.pretest -p:Configuration=Release -p:RestoreUseStaticGraphEvaluation=false -mt -m

# Test 3: WORKS - externals.csproj restored  
dotnet msbuild Build.proj -restore -t:Build -p:Subset=libs.pretest -p:Configuration=Release -m

Root Cause Analysis

NuGet's static graph restore uses an out-of-process tool (NuGet.Build.Tasks.Console) to evaluate projects and build the dependency graph. This tool receives global properties via IBuildEngine6.GetGlobalProperties().

When -mt mode is enabled, the MSBuildRestoreSessionId property appears to not be properly passed to the static graph evaluation, causing the condition '$(MSBuildRestoreSessionId)' != '' to evaluate as false during graph construction. This excludes the conditional ProjectReference from the restore graph.

Affected Code Paths

  • NuGet.Build.Tasks.RestoreTaskExStaticGraphRestoreTaskBase
  • NuGet.Build.Tasks.Console.MSBuildStaticGraphRestore.GetDependencyGraphSpec()
  • Global property serialization between MSBuild and the out-of-proc NuGet console

Workarounds

  1. Disable -mt for affected repos: Set <UseMSBuildMT>false</UseMSBuildMT> (current VMR approach)
  2. Disable static graph restore: Set RestoreUseStaticGraphEvaluation=false (slower)
  3. Change project pattern: Remove the MSBuildRestoreSessionId condition and always include the ProjectReference

Recommendation

This appears to be a bug in NuGet's static graph restore implementation when combined with MSBuild -mt mode. The fix likely needs to be in NuGet.Build.Tasks to ensure global properties (including MSBuildRestoreSessionId) are properly passed to the out-of-process evaluation in all modes.

Metadata

Metadata

Assignees

Labels

Area: Static GraphIssues with -graph, -isolate, and the related APIs.Priority:1Work that is critical for the release, but we could probably ship withouttriaged

Type

No fields configured for Bug.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions