Skip to content

Incorrect binding redirects generated for SqlClient's runtime dependencies #2541

Open

Description

@benjamin-hodgson

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):
ref\net462\Microsoft.Data.SqlClient.dll

The code assembly (lib\net462\Microsoft.Data.SqlClient.dll):
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.

Activity

  1. benjamin-hodgson commented on May 29, 2024

    @benjamin-hodgson
    Author

    I'm guessing #2414 would probably fix the issue once and for all if/when it gets merged.

  2. changed the title [-]SqlClient's reference assemblies should declare all dependencies[/-] [+]Incorrect binding redirects generated for SqlClient's runtime dependencies[/+] on May 29, 2024
  3. benjamin-hodgson commented on May 29, 2024

    @benjamin-hodgson
    Author

    Is this a dupe of #1900 ? If so I think that issue probably shouldn't have been closed.

  4. arellegue commented on May 29, 2024

    @arellegue
    Contributor

    We will investigate this issue and we'll get back to you when we have an update.

  5. kf-gonzalez2 commented on Jun 4, 2024

    @kf-gonzalez2

    @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?

  6. benjamin-hodgson commented on Jun 4, 2024

    @benjamin-hodgson
    Author

    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!

  7. zoeperryman commented on Sep 11, 2024

    @zoeperryman

    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:

        <PackageReference Include="Azure.Identity" Version="1.12.0" />
        <PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
    

    Results in the following error:

    Microsoft.Data.SqlClient.SqlException : Could not load file or assembly 'Azure.Core, Version=1.38.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8' or one of its dependencies.

    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.

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Azure.Core" publicKeyToken="92742159e12e44c8" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-1.40.0.0" newVersion="1.40.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0a613f4dd989e8ae" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-4.61.3.0" newVersion="4.61.3.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="Azure.Identity" publicKeyToken="92742159e12e44c8" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-1.12.0.0" newVersion="1.12.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>
    
  8. 2 remaining items

  9. benjamin-hodgson commented on Sep 12, 2024

    @benjamin-hodgson
    Author

    @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

  10. edwardneal commented on Sep 23, 2024

    @edwardneal
    Contributor

    @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:

    <dependentAssembly>
      <assemblyIdentity name="Azure.Core" publicKeyToken="92742159e12e44c8" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-1.40.0.0" newVersion="1.40.0.0" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="Azure.Identity" publicKeyToken="92742159e12e44c8" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-1.12.0.0" newVersion="1.12.0.0" />
    </dependentAssembly>
  11. JRahnama commented on Sep 23, 2024

    @JRahnama
    Contributor

    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

  12. edwardneal commented on Sep 23, 2024

    @edwardneal
    Contributor

    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.

  13. DavidHopkinsFbr commented on Jan 15, 2025

    @DavidHopkinsFbr

    I think this issue just bit me. I had Microsoft.Data.SqlClient 5.1.5 installed as a transitive dependency of Microsoft.EntityFramework.SqlServer 6.5.1 (which is the current version of that package). Microsoft.Data.SqlClient 5.1.5 depends on Microsoft.Identity.Client >= 4.56.0 and Azure.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 broke Microsoft.Data.SqlClient 5.1.5, causing runtime exceptions like this:

    System.TypeInitializationException: The type initializer for 'Microsoft.Data.SqlClient.SqlAuthenticationProviderManager' threw an exception.
    ---> System.IO.FileLoadException: Could not load file or assembly 'Microsoft.Identity.Client, Version=4.56.0.0, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae' or one of its dependencies. 
    The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
    

    I was able to eliminate the vulnerable dependencies and get a working Microsoft.Data.SqlClient by 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

  14. DavidHopkinsFbr commented on Jan 15, 2025

    @DavidHopkinsFbr

    I should also note that if Microsoft.Data.SqlClient 5.1.5 depends on vulnerable packages, and those packages cannot be upgraded without breaking SqlClient, then SqlClient 5.1.5 should also be flagged as Vulnerable. This will guide users to upgrade the whole Microsoft.Data.SqlClient package version and its dependencies to non-vulnerable versions, without runtime breakage.

  15. edwardneal commented on May 1, 2025

    @edwardneal
    Contributor

    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.

  16. cg110 commented on May 29, 2025

    @cg110

    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:

      <ItemGroup>
        <PackageReference Include="Azure.Identity" Version="1.14.0" />
        <PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
      </ItemGroup>
    
  17. moved this from To triage to Needs Response in SqlClient Boardon Jan 8, 2026
  18. moved this from Needs Response to Backlog in SqlClient Boardon Apr 1, 2026
  19. priyankatiwari08 commented on Sep 17, 2026

    @priyankatiwari08
    Contributor

    /triage

  20. github-actions commented on Sep 17, 2026

    @github-actions

    🔍 Triage Summary (on-demand re-triage)

    Check Result
    Issue type Bug
    Environment All required environment details provided for investigation
    Area Area\Netfx
    Duplicates Potentially related: #1900, #2304, #2286
    Regression Likely recurring regression — repro was fixed in v5.2.1 (via PR #2462, rebuilding against newer Azure.Identity/Azure.Core) but reopened each time Azure.Core/Azure.Identity ship a new major, most recently reported as still reproducible on 6.0.2 (May 2025)

    Analysis

    This is a long-standing, recurring bug (P1) affecting net462/net472 consumers: SqlClient's ref (reference) assembly under netfx/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's ResolveAssemblyReferences/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 in app.config/web.config. This causes FileLoadException/TypeInitializationException at runtime whenever a project's other dependencies pull in a different (often newer) version of Azure.Core or Microsoft.Identity.Client than 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

    Note: This triage summary is auto-generated by an AI agent. The analysis and suggestions above have not been verified by a human maintainer. Please treat as preliminary guidance only.

    Generated by SqlClient Issue Auto-Triage for #2541 · copilot · auto · 46.6 AIC · ⌖ 13.3 AIC · ⊞ 11.9K · ◷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions