runtime: System.Numerics.Vectors.dll fails to load

This relates to use of the System.Numerics.Vectors (nuget package 4.5) in a dotnet standard 2.0 library, and consuming that library from a Windows .NET Framework application.

When the runtime attempts to load System.Numerics.Vectors this error is reported…

System.IO.FileNotFoundException
  HResult=0x80070002
  Message=Could not load file or assembly 'System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

Reverting to System.Numerics.Vectors 4.4.0 resolves the problem.

Example code:

dotnet standard 2.0 library class…

namespace FooLib
{
    public class Class1
    {
        public void DoStuff(int[] arr)
        {
            var va = new Vector<int>(arr, 0);
            var vb = new Vector<int>(arr, 4);
            var vc = va + vb;
            vc.CopyTo(arr, 0);
        }
    }
}

.NET Franework 4.7 console app

    class Program
    {
        static void Main(string[] args)
        {
            int[] arr = new int[32];

            Class1 c1 = new Class1();
            c1.DoStuff(arr);

            Console.WriteLine(arr[0]);
        }
    }

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 22 (21 by maintainers)

Commits related to this issue

Most upvoted comments

This sounds much more similar to the problem I had that led me to this issue. In my case, a user has a net47 web site (i.e. no csproj) that references my netstandard2.0 library in a Nuget package. That library package references System.Numerics.Vectors 4.4.0. Since the web site is using packages.config, Nuget Package Manager pulls in System.Numerics.Vectors directly as a dependency when my library is referenced. The site owner then sees the update to System.Numerics.Vectors 4.5.0 offered when she views her available Nuget updates and pulls it in even though her only reference to it is through my library. Boom, my library breaks and the only fix is to either roll back the package update or create a bindingRedirect manually. Is there an equivalent to AutoGenerateBindingRedirects that can be used in cases like that?

I suspect because the reference assembly and lib assembly versions are different within the Nuget package, the same scenario would play out even if I update my library to reference 4.5.0 directly, because I’m still building against a 4.1.3.0 reference and the bin version will still be 4.1.4.0.

@colgreen the following app.config fixes your unit test project up, same as with the web site I mentioned

<configuration>
	<runtime>
		<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
			<dependentAssembly>
				<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a"/>
				<bindingRedirect oldVersion="4.0.0.0-4.1.4.0" newVersion="4.1.4.0"/>
			</dependentAssembly>
		</assemblyBinding>
	</runtime>
</configuration>

@eerhardt Here you go:

VectorProto-v1.zip

It took a while to distill the problem down to a demo solution with only the relevant aspects. In summary, the attached solution contains a .NET Framework 4.7 Unit Test project that refers to a dotnet standard 2.0 library project.

Both the unit test project and the lib project refer to the System.Numerics.Vectors nuget directly, in the original solution this was because there was a unit test that indicates if the hardware acceleration is enabled or not:

        [TestMethod]
        public void TestHardwareAccelerated()
        {
            if(!Vector.IsHardwareAccelerated) {
                Assert.Inconclusive("Hardware accelerations not available. Hardware acceleration is available on supporting CPUs only, and only for x64 builds with optimization enabled (i.e. release builds).");
            }
            ...
        }

As well as other tests against the code in the lib that uses System.Numerics.Vectors if IsHardwareAccelerated == true.

Hence, when I saw the new SNV nuget I updated both projects, ran my unit tests and they started failing! I reverted back to nuget 4.4.0 and they all passed.

Looking deeper (for tracking purposes) this was https://github.com/dotnet/corefx/issues/32457

Thanks for the explanation @eerhardt. I wasn’t aware of the GenerateBindingRedirectsOutputType setting, but I guess that doesn’t help with a web site anyway since there’s no project file to put that in. And it’s certainly not intuitive even if that solution is an option. I get that it’s by design and is mitigated in certain toolsets, but man is that a mess…

As a library author, it sucks for me, because a certain (not insignificant, I think) segment of my users will download my package and immediately find it doesn’t work. That reflects poorly on me, even if the fix is to create a bindingRedirect on their side.

As a general user of those packages, it sucks for me because it’s extremely counter-intuitive that I should require a bindingRedirect (whether automagical or manual) to use the library version contained in a package version that I have explicitly and directly referenced. And it’s not exactly easy to track down the correct version to create the bindingRedirect to if you have to add it manually.

If I’m understanding @ericstj ’s explanation correctly, the implementation assembly version number is bumped even though the reference assembly version is frozen just so that desktop users who have GAC’ed the assemblies pick up the new version. If that’s the case, you’ve put the needs of two groups of users at odds with one another. I’d argue (and I’m certainly biased) that people using Nuget distribution as intended should have a clean and intuitive experience and the people who do odd things like GAC-ing a Nuget-distributed assembly should get the pain they’ve brought on themselves. It certainly would work better from my perspective if the implementation assembly version number stayed put once the reference assembly version is frozen.

Thanks @colgreen and @saucecontrol. I am able to repro the problem, and agree with @saucecontrol that the reason this is failing is that the netstandard2.0 ref assembly (and all previous versions of the package) have an AssemblyVersion less than 4.1.4, and in the latest NuGet package (4.5.0) has an implementation assembly with AssemblyVersion 4.1.4. When assemblies are referencing different versions of another assembly on .NET Framework projects, you have to use an assembly binding redirect in order for the runtime to load it correctly. (Note on .NET Core this redirect happens automatically using the .deps.json file and TPA list).

Is there an equivalent to AutoGenerateBindingRedirects that can be used in cases like that?

I wasn’t part of the original AutoGenerateBindingRedirects implementation, so I might not have all the correct info. Hopefully someone corrects me if I’m wrong. But it appears to only kick in when both AutoGenerateBindingRedirects and GenerateBindingRedirectsOutputType are set to true. GenerateBindingRedirectsOutputType gets defaulted to true when you are an exe or winexe OutputType project. But when you are a unit test or web project (like you both describe), the OutputType isn’t set to exe. So to get the binding redirects to kick in, I needed to set both properties in the unit test project:

    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>

I suspect because the reference assembly and lib assembly versions are different within the Nuget package, the same scenario would play out even if I update my library to reference 4.5.0 directly, because I’m still building against a 4.1.3.0 reference and the bin version will still be 4.1.4.0.

Assuming your library is targeting netstandard2.0, then you are correct.


This issue is still “closed”, but I agree it isn’t a dupe of https://github.com/dotnet/sdk/issues/901. Instead, it is by design as @ericstj mentions above - the netstandard2.0 ref assembly was pinned to 4.1.3 because it was made inbox in .NET Core 2.0. Using assembly binding redirects is the correct fix here.

This repros on my machine on all tfms from net461 to net472 only when the System.Numerics.Vectors package is added inside a netstandard2.0 library. Referencing it directly from netfx works as expected.