Repository navigation
Incorrect binding redirects generated for SqlClient's runtime dependencies #2541
Description
Describe the bug
SqlClient was compiled with Azure.Core version 1.35.0.0. When building a project using version 1.38.0.0 (or indeed any other version), the appropriate binding redirect is not generated. This results in FileLoadExceptions in the AD authentication codepath - example:
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'Azure.Core, Version=1.35.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
at Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider.AcquireTokenAsync(SqlAuthenticationParameters parameters)
at Program.Main() in D:\test\Program.cs:line 7
(My minimal repro, below, trips on Azure.Core but I've also seen errors mentioning ValueTuple and System.Threading.Tasks.Extensions in other contexts. I believe they're all due to the same issue.)
The problem here is that the ResolveAssemblyReferences target (which is responsible for determining which libraries need binding redirects) consumes reference assemblies from Nuget (when they exist), and SqlClient's reference assemblies do not declare the library's runtime dependency on Azure.Core.
The reference assembly in ILSpy (ref\net462\Microsoft.Data.SqlClient.dll):

The code assembly (lib\net462\Microsoft.Data.SqlClient.dll):

This means ResolveAssemblyReferences doesn't realise there's a conflict (it thinks SqlClient doesn't require Azure.Core at all) so fails to generate the correct binding redirects. When SqlClient's code assembly is deployed into the bin folder and run, it requires version 1.35, and, absent the required binding redirect, it dies because it can only find 1.38.
To reproduce
The issue manifests when the other assemblies in your compilation all reference v1.38 of the Azure.Core assembly. This combination of versions reproduces the issue (though there are other scenarios that produce the same issue with various other assemblies):
<!-- test.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.11.2" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
</ItemGroup>
</Project>// Program.cs
using Microsoft.Data.SqlClient;
public class Program
{
public static void Main()
{
// We just need to cause AcquireTokenAsync to be jitted.
// In practice this'll typically happen during a call to
// SqlConnection.Open() when authenticating via AD
new ActiveDirectoryAuthenticationProvider().AcquireTokenAsync(null);
}
}Build this project and observe the lack of binding redirect for Azure.Core (and others, eg Tasks.Extensions) in bin\Debug\net472\test.exe.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0a613f4dd989e8ae" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.60.3.0" newVersion="4.60.3.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.ProtectedData" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>Running the project using dotnet run causes the exception above.
Expected behavior
The reference assemblies for SqlClient should correctly declare all of the library's (immediate) runtime dependencies. This will allow ResolveAssemblyReference to solve the versions correctly and generate the required binding redirects.
Further technical details
Microsoft.Data.SqlClient version: 5.2.0 or 3.1.5 (but probably others too)
.NET target: net472
SQL Server version: Any
Operating system: Windows 11
Additional context
Probably not relevant, but: I found this issue in a large repo with thousands of projects. The repo is in the process of being migrated off of CoreXT and onto CentralPackageVersions.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsBacklog
- StatusShow more project fieldsNeeds Investigation
Activity
benjamin-hodgson commentedon May 29, 2024
I'm guessing #2414 would probably fix the issue once and for all if/when it gets merged.
[-]SqlClient's reference assemblies should declare all dependencies[/-][+]Incorrect binding redirects generated for SqlClient's runtime dependencies[/+]benjamin-hodgson commentedon May 29, 2024
Is this a dupe of #1900 ? If so I think that issue probably shouldn't have been closed.
arellegue commentedon May 29, 2024
We will investigate this issue and we'll get back to you when we have an update.
kf-gonzalez2 commentedon Jun 4, 2024
@benjamin-hodgson Hotfix 5.2.1 is out now, would you mind testing with this version and letting us know if this is still an issue please?
benjamin-hodgson commentedon Jun 4, 2024
Looks like this'll work for now, at least for our purposes, but it's liable to become broken again as new versions of the upstream libraries come out. The root cause is the missing references in the ref assemblies. (I don't think this issue should be closed.)
Thanks for turning this hotfix around so quickly!
zoeperryman commentedon Sep 11, 2024
With the release of Azure.Identity 1.12 (and Azure.Core 1.40) this is broken again. My full framework projects (net462 and net48) fail to automatically generate the binding redirects, it needs to be done manually.
Referencing the following project combination:
Results in the following error:
Adding the following bindings manually to a app/web.config resolves the problem. But this should be done automatically when automatic binding redirects are enabled.
2 remaining items
benjamin-hodgson commentedon Sep 12, 2024
@JRahnama This is a real bug in the way the SqlClient package is distributed - please see my original detailed bug report.
It was worked-around in v5.2.1 by rebuilding SqlClient against the latest version of Azure.Identity/Azure.Core but as predicted it became broken again when new versions of those upstream packages were released.
To fix the bug you could either update your dependencies once again (ie, continue working around it) or get #2414 merged
edwardneal commentedon Sep 23, 2024
@benjamin-hodgson I think this should be fixed (in the absence of auto-generated reference assemblies) by #2878.
I've synced the references between the runtime assembly and the reference assembly, and pushed it through CI. Could you test with the package from this CI build please? The direct download URL of the ZIP file containing the .nupkg is here
To test, I added a reference to the version of the package (6.0.0-pull.126701, which has a transitive reference to Azure.Identity 1.11.4), then to Azure.Identity 1.12.0. I can see that VS' automatic binding redirects have added a few new entries to app.config. The relevant excerpt:
JRahnama commentedon Sep 23, 2024
Here is the package from that build. Simply change the extension to .nupkg. Please note, this is an unsigned test package and is not intended for production use.
Microsoft.Data.SqlClient.6.0.0-pull.126701.zip
edwardneal commentedon Sep 23, 2024
Thanks @JRahnama - and yes, it's definitely not intended for production use. This package isn't designed to be anything more than a sanity check to make sure that the downstream projects referencing SqlClient build and that VS generates the correct binding redirects in the output app.config.
DavidHopkinsFbr commentedon Jan 15, 2025
I think this issue just bit me. I had
Microsoft.Data.SqlClient 5.1.5installed as a transitive dependency ofMicrosoft.EntityFramework.SqlServer 6.5.1(which is the current version of that package).Microsoft.Data.SqlClient 5.1.5depends onMicrosoft.Identity.Client >= 4.56.0andAzure.Identity >= 1.10.3, both of which minimum versions are flagged as vulnerable in the NuGet package repository. In a .NET 4.8 WPF project (with "auto-generate binding redirects" turned on), upgrading those transitive dependencies to fix the vulnerabilities brokeMicrosoft.Data.SqlClient 5.1.5, causing runtime exceptions like this:I was able to eliminate the vulnerable dependencies and get a working
Microsoft.Data.SqlClientby upgrading it to 5.2.2, but a permanent fix for similar loading failures in the future would be welcome.Related StackOverflow question: https://stackoverflow.com/questions/79356952/assembly-loading-failures-in-microsoft-data-sqlclients-dependencies/79357028#79357028
DavidHopkinsFbr commentedon Jan 15, 2025
I should also note that if
Microsoft.Data.SqlClient 5.1.5depends on vulnerable packages, and those packages cannot be upgraded without breakingSqlClient, thenSqlClient 5.1.5should also be flagged as Vulnerable. This will guide users to upgrade the wholeMicrosoft.Data.SqlClientpackage version and its dependencies to non-vulnerable versions, without runtime breakage.edwardneal commentedon May 1, 2025
I've just re-tested this with the latest versions (6.0.2, 5.2.3 and 5.1.7) of each SqlClient release, and this should now be working properly.
cg110 commentedon May 29, 2025
It's still not working with 6.0.2. MSbuild picks up the ref dll and uses it to work out if any suggesting binding redirects are needed. As the ref version doesn't mention all the dlls it doesn't cause redirects to be generated.
Could you just remove the ref dll? (as very few nugets provide a ref) and provide just the lib version, which means that msbuild will then use the lib to work out any binding redirects, and get it right.
Alternatively is this actually an msbuild/.net sdk problem, and it should be using the runtime dlls (IE lib) not the compile time ones (ref) when working out suggested binding redirects.
The reproduction at the start of this ticket is still valid with newer nugets, eg:
priyankatiwari08 commentedon Sep 17, 2026
/triage
github-actions commentedon Sep 17, 2026
🔍 Triage Summary (on-demand re-triage)
Area\NetfxAnalysis
This is a long-standing, recurring bug (P1) affecting
net462/net472consumers: SqlClient's ref (reference) assembly undernetfx/ref/doesn't declare the same runtime dependencies (Azure.Core,Microsoft.Identity.Client,System.Threading.Tasks.Extensions, etc.) as the lib (implementation) assembly. Because MSBuild'sResolveAssemblyReferences/binding-redirect generation consults the ref assembly at compile time, it under-reports SqlClient's transitive dependencies, so Visual Studio/MSBuild fails to auto-generate the correct<bindingRedirect>entries inapp.config/web.config. This causesFileLoadException/TypeInitializationExceptionat runtime whenever a project's other dependencies pull in a different (often newer) version ofAzure.CoreorMicrosoft.Identity.Clientthan the one SqlClient's lib assembly was built against. It was patched once per-release by realigning versions (PR #2462) and a more durable fix (synchronizing ref vs. lib references, PR #2878) was proposed, but per the May 2025 comment the repro still reproduces on 6.0.2, and the root cause (ref/lib dependency mismatch) has not been permanently closed. Given the ongoing unified-project/ref-consolidation effort (see.github/plans/apicompat-ref-assembly-validation.md, tracked under PR #3963), this issue is directly relevant to verify as part of that work.Next Steps
CompareMdsRefAssembliesApiCompat target) already restores parity between theref/andsrc/(lib) dependency declarations fornet462, and if not, extend theref/Microsoft.Data.SqlClient.csprojPackageReference/Referenceitems so they match the runtime assembly's transitive dependencies (Azure.Core,Azure.Identity,Microsoft.Identity.Client,System.Threading.Tasks.Extensions, etc.) per the currentDirectory.Packages.propsversions.Azure.Identity/Azure.Coreto confirm whether it's still broken today, since the last confirmation (June 2025 comment) said it was still failing on 6.0.2.CompareMdsRefAssembliesApiCompat/dependency-comparison target) so this doesn't silently reappear on the next Azure.Core/Azure.Identity bump.