Skip to content

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 #4299

@NenadM

Description

@NenadM

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)

  1. 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
  2. Ensure System.Collections.Immutable (e.g., version 9.0.2) is a dependency

  3. 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)

  4. Run paket update --redirect for the solution

  5. 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>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions