paket update --redirect generates incorrect System.Collections.Immutable binding redirect (9.0.0.0 instead of 9.0.2.0) with .NET Core-only transitive dependency
Problem Description
When using paket update --redirect in a mixed .NET Framework / .NET Standard solution, Paket sometimes generates an incorrect app.config binding redirect for System.Collections.Immutable. Specifically, despite paket.lock and project.assets.json resolving the package version to 9.0.2, the newVersion in app.config is set to 9.0.0.0 instead of 9.0.2.0 for certain .NET Framework 4.8 projects. This leads to a System.IO.FileLoadException at runtime.
This behavior is specifically observed when a project transitively depends on a NuGet package that is .NET Core-only (e.g., targeting netstandard2.0 and net6.0 but not .NET Framework). In our case, this problematic dependency is part of the Roslyn compiler.
Expected Behavior
For a .NET Framework 4.8 project, paket update --redirect should generate a binding redirect for System.Collections.Immutable (package version 9.0.2) with newVersion="9.0.2.0", as this corresponds to the net462 asset of the package, which is compatible and preferred for .NET Framework 4.8.
Actual Behavior
For some .NET Framework 4.8 projects in the solution, paket update --redirect generates:
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable"
publicKeyToken="b03f5f7f11d50a3a"
culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535" newVersion="9.0.0.0" />
</dependentAssembly>
This causes a System.IO.FileLoadException at runtime:
System.IO.FileLoadException : Could not load file or assembly 'System.Collections.Immutable, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Steps to Reproduce (Conceptual)
-
Set up a solution with a mix of .NET Framework 4.8 and netstandard2.0 projects. Your setup includes:
- An app project (executable, .NET 4.8)
- A DLL output project (also .NET 4.8) in the same solution
- An internal NuGet DLL (targets netstandard2.0 and net4.8)
- This internal NuGet DLL uses a Roslyn compiler dependency
- System.Collections.Immutable is used by some DLL output projects in your original solution as well
-
Ensure System.Collections.Immutable (e.g., version 9.0.2) is a dependency
-
Ensure the Roslyn compiler dependency is the version that is .NET Core-only (e.g., targeting netstandard2.0 and net6.0 but not .NET Framework)
-
Run paket update --redirect for the solution
-
Observe that .NET Framework 4.8 projects that depend on the path involving the .NET Core-only Roslyn dependency receive the newVersion="9.0.0.0" binding redirect for System.Collections.Immutable
Environment
- Paket Version: 9.0.2+a9b12aaeb8d8d5e47a415a3442b7920ed04e98e0
- .NET Framework Version: 4.8
- Other relevant package: System.Collections.Immutable (package version 9.0.2)
- Problematic Transitive Dependency Type: A NuGet package (part of Roslyn compiler) targeting netstandard2.0 and net6.0 but not .NET Framework
Hypothesis of the Cause
It appears that Paket's asset selection logic for binding redirects, when encountering a transitive dependency that only targets netstandard2.0 (or newer, without .NET Framework), might incorrectly prioritize or default to the netstandard2.0 asset of System.Collections.Immutable (which has assembly version 9.0.0.0) even for .NET Framework 4.8 projects. This happens despite the net462 asset (assembly version 9.0.2.0) being available within the same 9.0.2 package and being more directly compatible with the .NET Framework 4.8 target.
Workaround
Manually overriding the newVersion in the affected app.config files to 9.0.2.0 resolves the runtime FileLoadException. Example:
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable"
publicKeyToken="b03f5f7f11d50a3a"
culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535" newVersion="9.0.2.0" />
</dependentAssembly>
paket update --redirectgenerates incorrect System.Collections.Immutable binding redirect (9.0.0.0 instead of 9.0.2.0) with .NET Core-only transitive dependencyProblem Description
When using
paket update --redirectin a mixed .NET Framework / .NET Standard solution, Paket sometimes generates an incorrectapp.configbinding redirect forSystem.Collections.Immutable. Specifically, despitepaket.lockandproject.assets.jsonresolving the package version to9.0.2, thenewVersioninapp.configis set to9.0.0.0instead of9.0.2.0for certain.NET Framework 4.8projects. This leads to aSystem.IO.FileLoadExceptionat runtime.This behavior is specifically observed when a project transitively depends on a NuGet package that is .NET Core-only (e.g., targeting
netstandard2.0andnet6.0but not.NET Framework). In our case, this problematic dependency is part of the Roslyn compiler.Expected Behavior
For a
.NET Framework 4.8project,paket update --redirectshould generate a binding redirect forSystem.Collections.Immutable(package version9.0.2) withnewVersion="9.0.2.0", as this corresponds to thenet462asset of the package, which is compatible and preferred for.NET Framework 4.8.Actual Behavior
For some
.NET Framework 4.8projects in the solution,paket update --redirectgenerates:This causes a
System.IO.FileLoadExceptionat runtime:Steps to Reproduce (Conceptual)
Set up a solution with a mix of .NET Framework 4.8 and netstandard2.0 projects. Your setup includes:
Ensure
System.Collections.Immutable(e.g., version 9.0.2) is a dependencyEnsure the Roslyn compiler dependency is the version that is .NET Core-only (e.g., targeting netstandard2.0 and net6.0 but not .NET Framework)
Run
paket update --redirectfor the solutionObserve that .NET Framework 4.8 projects that depend on the path involving the .NET Core-only Roslyn dependency receive the
newVersion="9.0.0.0"binding redirect for System.Collections.ImmutableEnvironment
Hypothesis of the Cause
It appears that Paket's asset selection logic for binding redirects, when encountering a transitive dependency that only targets netstandard2.0 (or newer, without .NET Framework), might incorrectly prioritize or default to the netstandard2.0 asset of
System.Collections.Immutable(which has assembly version 9.0.0.0) even for .NET Framework 4.8 projects. This happens despite the net462 asset (assembly version 9.0.2.0) being available within the same 9.0.2 package and being more directly compatible with the .NET Framework 4.8 target.Workaround
Manually overriding the
newVersionin the affectedapp.configfiles to9.0.2.0resolves the runtime FileLoadException. Example: