From 1863a4b2694a938e8525c6b303994882f9fa1a1a Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Mon, 6 Apr 2026 10:09:19 -0300 Subject: [PATCH] Fix LoginWithFailover missing parser state check LoginWithFailover() was missing the _parser?.State check that LoginNoFailover() already has. This caused transient errors (40613, 42108, 42109) to trigger failover alternation instead of being thrown immediately for the outer ConnectRetryCount loop to handle. Added the same parser state check so that login-phase errors (parser open) throw immediately while network errors (parser closed) continue failover alternation. Fixes #4139 --- .../Data/SqlClient/Connection/SqlConnectionInternal.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs index cf0a296b30..ef563fcccd 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs @@ -3662,7 +3662,15 @@ private void LoginWithFailover( continue; } - if (IsDoNotRetryConnectError(sqlex) || timeout.IsExpired) + // If state != closed, indicates that the parser encountered an error while + // processing the login response (e.g. an explicit error token). Transient + // network errors that impact connectivity will result in parser state being + // closed. Only network-level errors should trigger failover alternation; + // login-phase errors (like transient errors) should be thrown so they can + // be handled by the outer ConnectRetryCount loop. + if (_parser?.State is not TdsParserState.Closed || + IsDoNotRetryConnectError(sqlex) || + timeout.IsExpired) { // No more time to try again. // Caller will call LoginFailure()