Skip to content

Stack overflow caused by SqlConfigurableRetryLogicLoader.Defaul_resolving #2214

Open

Description

@sfiruch

Describe the bug

I have an Blazor web app on .NET 7, using EF and Microsoft.Data.SqlClient 5.0.2. The web app was running fine for several months. It crashed this morning, with the following exception:

Stack overflow.
   at System.RuntimeMethodHandle._GetCurrentMethod(System.Threading.StackCrawlMark ByRef)
   at System.Reflection.MethodBase.GetCurrentMethod()
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.Default_Resolving(System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.GetFirstResolvedAssemblyFromResolvingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingResolvingEvent(IntPtr, System.Reflection.AssemblyName)
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.MakeFullPath(System.String, System.String, System.String)
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.Default_Resolving(System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.GetFirstResolvedAssemblyFromResolvingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingResolvingEvent(IntPtr, System.Reflection.AssemblyName)
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.MakeFullPath(System.String, System.String, System.String)
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.Default_Resolving(System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.GetFirstResolvedAssemblyFromResolvingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingResolvingEvent(IntPtr, System.Reflection.AssemblyName)
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.MakeFullPath(System.String, System.String, System.String)
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.Default_Resolving(System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.GetFirstResolvedAssemblyFromResolvingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingResolvingEvent(IntPtr, System.Reflection.AssemblyName)
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.MakeFullPath(System.String, System.String, System.String)
   at Microsoft.Data.SqlClient.SqlConfigurableRetryLogicLoader.Default_Resolving(System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.GetFirstResolvedAssemblyFromResolvingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingEvent(System.Reflection.AssemblyName)
   at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingResolvingEvent(IntPtr, System.Reflection.AssemblyName)
...

To reproduce

Have restarted the app, but was not (yet) successful to repro.

Didn't configure any special options, environment variables, etc. AFAIK. This is the connection string (password etc. changed):
Data Source=tcp:super-secret.database.windows.net,1433;Initial Catalog=mywebsite.com;Integrated Security=False;Persist Security Info=False;User ID=super-secret;Password=123456;Encrypt=True

Further technical details

Microsoft.Data.SqlClient version: 5.0.2
.NET target: 7.0
SQL Server version: Azure SQL
Operating system: Ubuntu 20.04.3 LTS

Activity

  1. ErikEJ commented on Nov 12, 2023

    @ErikEJ
    Contributor

    Have you tried 5.1.2 ?

  2. sfiruch commented on Nov 13, 2023

    @sfiruch
    Author

    Have you tried 5.1.2 ?

    Yes, this is the version that's running now.

    I didn't notice any changes in the relevant areas (but didn't look very hard). It'll take months to determine whether the problem is fixed. I had hoped that the person working in this area could make sense of the stack overflow immediately.

  3. arellegue commented on Nov 25, 2023

    @arellegue
    Contributor

    @deiruch, before I can begin investigation, may I ask for a repro code, please? I would like to know how SqlConfigurableRetryLogic is configured in your code.

  4. sfiruch commented on Nov 26, 2023

    @sfiruch
    Author

    @deiruch, before I can begin investigation, may I ask for a repro code, please? I would like to know how SqlConfigurableRetryLogic is configured in your code.

    I only have a full website that showed the behavior after running for several months. The source code is private. Should I share the code with you?

    The code is not special at all: It's using EF Core 7.0.13.0 with default options for database access. I didn't configure SqlConfigurableRetryLogic manually.

  5. arellegue commented on Dec 5, 2023

    @arellegue
    Contributor

    @deiruch, could you at least provide information such as:

    1. App.config
    2. appsettings.json
    3. In your DbContext class, the content of OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  6. sfiruch commented on Dec 6, 2023

    @sfiruch
    Author

    Sure, I'm happy to! But I fear there's nothing of interest in there. It's really just using defaults.

    App.config

    Does not exist

    appsettings.json

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "EmailSender": {
        "Host": "smtp-pulse.com",
        "Port": 2525,
        "EnableSSL": false,
        "UserName": "123",
        "Password": "123",
        "From": "123@secret.com"
      },
      "AllowedHosts": "*",
      "LettuceEncrypt": {
        "AcceptTermsOfService": true,
        "DomainNames": [ "secret.com" ],
        "EmailAddress": "123@secret.com",
        "AllowedChallengeTypes": "Http01",
        "UseStagingServer": false
      },
      "https_port": 443,
      "Kestrel": {
        "Endpoints": {
          "Http": {
            "Url": "http://*:80"
          },
          "Https": {
            "Url": "https://*:443"
          }
        }
      }
    }

    OnConfiguring

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    #warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
            => optionsBuilder.UseSqlServer("Data Source=tcp:secret.database.windows.net,1433;Initial Catalog=secret;Integrated Security=False;Persist Security Info=False;User ID=secret;Password=123;Encrypt=True");
  7. moved this from To triage to Backlog in SqlClient Boardon Jan 12, 2026
  8. priyankatiwari08 commented on Sep 17, 2026

    @priyankatiwari08
    Contributor

    /triage

  9. 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\Engineering
    Duplicates Potentially related: #4623
    Regression Not indicated (reporter confirmed same stack overflow reproduced on 5.1.2 as well as 5.0.2)

    Analysis

    The reported StackOverflowException originates in SqlConfigurableRetryLogicLoader.Default_Resolving, where the AssemblyLoadContext.Default.Resolving event handler calls MakeFullPath/LoadFromAssemblyPath, which under certain conditions (e.g. failing to find the assembly, or a load failure that re-triggers resolution) appears to recursively re-enter the same Resolving event, eventually overflowing the stack. This is severe (P1) since a StackOverflowException is fatal and unrecoverable, crashing the entire process without warning, and it's non-deterministic (the reporter could not repro on demand after a restart, suggesting a race condition or state built up over time, consistent with the AssemblyLoadContext resolving handler being globally shared/reentrant). No repro code is available, and the reporter's usage is default EF Core UseSqlServer configuration without explicit configurable-retry-logic settings, meaning the resolving handler was likely subscribed unintentionally or left subscribed longer than necessary. This aligns with the current in-repo AssemblyResolutionSubscription pattern (subscribe/unsubscribe around resolution, restricted to #if NET), which appears to have been introduced later to scope the handler's lifetime — but it's unclear if it fully addresses recursive self-triggering during resolution failure.

    Next Steps

    • Assign this issue to Copilot coding agent to investigate whether Default_Resolving in SqlConfigurableRetryLogicLoader.cs can recursively re-enter itself when MakeFullPath/LoadFromAssemblyPath triggers additional Resolving events (e.g., when loading a dependent assembly that itself can't be resolved, or Windows/Linux path/probing differences causing repeated re-invocation), and confirm the existing AssemblyResolutionSubscription scoping (subscribe only while a custom retry-logic type is configured, unsubscribe immediately after) fully prevents this recursion path, adding a guard/reentrancy check if not.
    • Related: Redesign configurable retry logic assembly loading (dedicated ALC and/or explicit registration API) #4623 proposes redesigning this assembly loading mechanism entirely (dedicated ALC and/or explicit registration API) — recommend reviewing that issue in parallel, as a full redesign may be the most robust fix rather than a targeted patch.
    • Since the reporter could not produce a reliable repro, recommend adding defensive guards (e.g., depth/reentrancy tracking, or unsubscribing the handler before invoking LoadFromAssemblyPath to avoid nested resolution triggering the same handler) as a general hardening measure even without an exact repro.

    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 #2214 · copilot · auto · 83.5 AIC · ⌖ 13.2 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