You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unable to cast object of type 'Microsoft.Data.ProviderBase.DbConnectionClosedConnecting' to type 'Microsoft.Data.SqlClient.SqlInternalConnectionTds' #3314
When I start the NET CORE API, and refresh my website client. I got this exception
System.InvalidCastException: Unable to cast object of type 'Microsoft.Data.ProviderBase.DbConnectionClosedConnecting' to type 'Microsoft.Data.SqlClient.SqlInternalConnectionTds'.
at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
at Microsoft.Data.SqlClient.SqlConnection.Open()
To reproduce
Not sure how to reproduce. I see this exception happened when the API is just starting, or the API wakup after idle a long time
Expected behavior
A clear and concise description of what you expected to happen.
It's really hard to reproduce it.
As I said, sometimes I get it when I start the local API and refresh my local website, it calls the local API, and I get this exception in the log file. In the production hosting, when the IIS sleeps because no requests, and I access the production website, I get the same exception. But if I continue calling the API, I never get this exception
More information, I set up the DI for the SQL class with the scope is Singleton.
For now, this bug is resolved when I remove the SQL DI and create the dynamic SQL instance each time I call to DB
@mrvogiacu Thank you for the response. I'll discuss this internally with the team and get back to you.
Meanwhile, a search on this exception returned following threads. Does any of the workaround discussed in these threads work for you? dotnet/efcore#11595 DevExpress/DevExtreme.AspNet.Data#352 (comment)
Hi @apoorvdeshmukh ,
I try to research and not see the link you gave me above. I take a look, and all of them talk about EF, but I am using Dapper with store procedure.
I guess the problem can be DI, because after I stopped using DI and let the SQL instance be created by my DA class, I did not get this exception anymore.
Before this exception, I was already using Scoped DI and got another problem :D
After investigating the codebase, this InvalidCastException originates from a TOCTOU (time-of-check-time-of-use) race condition in SqlConnection.TryOpenInner().
Thread A calls Open() → TryOpenInner() → TryOpenConnection() completes successfully, setting _innerConnection to a valid SqlConnectionInternal.
Thread B concurrently calls Open() (or another state-changing operation) on the sameSqlConnection instance, setting _innerConnection to DbConnectionClosedConnecting (a singleton transitional state marker).
Thread A reads InnerConnection for the cast — but now it's DbConnectionClosedConnecting, which is not assignable to SqlConnectionInternal → InvalidCastException.
The key issue is that _innerConnection is read twice without synchronization: once for TryOpenConnection() and again for the cast. The field is modified via both Interlocked.CompareExchange (in SetInnerConnectionFrom) and plain assignment (in SetInnerConnectionTo), so there is no consistent locking.
Why it happens after idle / on startup
IIS app pool recycling or connection pool pruning invalidates idle connections
New requests trigger concurrent Open() calls on shared connection instances
The pool state transitions can race with new connection attempts
Most likely user-side cause
SqlConnection is not thread-safe. This exception almost always means the same SqlConnection instance is being used from multiple threads simultaneously. Common causes in ASP.NET Core:
SqlConnection registered as Singleton in DI (should be Scoped or Transient)
A static SqlConnection field shared across requests
Missing await on async operations, causing overlapping operations on the same connection
Recommendation
Immediate fix: Ensure each database operation creates its own SqlConnection:
// ✅ Correct: new connection per operationusingvarconnection=newSqlConnection(connectionString);awaitconnection.OpenAsync();
The TryOpenInner method could be hardened to detect this state and throw a more descriptive error (e.g., "Connection state changed unexpectedly. SqlConnection is not thread-safe — do not share instances across threads.") instead of the opaque InvalidCastException.
Could you confirm:
How is your SqlConnection created/managed? (DI registration? static field? per-request?)
Which version of Microsoft.Data.SqlClient are you using? (The stack trace references SqlInternalConnectionTds which has been renamed to SqlConnectionInternal in recent versions.)
Instead of using Sql instance with the Singleton scope, my DA class (DI with Scoped scope) inherits the Sql class and creates a Sql instance for each request.
Activity
apoorvdeshmukh commentedon May 5, 2025
@mrvogiacu Can you provide any steps to reproduce this issue? Can you mention the specific API when you are seeing this issue?
mrvogiacu commentedon May 5, 2025
Hi @apoorvdeshmukh ,
It's really hard to reproduce it.
As I said, sometimes I get it when I start the local API and refresh my local website, it calls the local API, and I get this exception in the log file. In the production hosting, when the IIS sleeps because no requests, and I access the production website, I get the same exception. But if I continue calling the API, I never get this exception
More information, I set up the DI for the SQL class with the scope is Singleton.
For now, this bug is resolved when I remove the SQL DI and create the dynamic SQL instance each time I call to DB
apoorvdeshmukh commentedon May 5, 2025
@mrvogiacu Thank you for the response. I'll discuss this internally with the team and get back to you.
Meanwhile, a search on this exception returned following threads. Does any of the workaround discussed in these threads work for you?
dotnet/efcore#11595
DevExpress/DevExtreme.AspNet.Data#352 (comment)
mrvogiacu commentedon May 5, 2025
Hi @apoorvdeshmukh ,
I try to research and not see the link you gave me above. I take a look, and all of them talk about EF, but I am using Dapper with store procedure.
I guess the problem can be DI, because after I stopped using DI and let the SQL instance be created by my DA class, I did not get this exception anymore.
Before this exception, I was already using
ScopedDI and got another problem :D10 remaining items
paulmedynski commentedon Apr 10, 2026
Analysis
After investigating the codebase, this
InvalidCastExceptionoriginates from a TOCTOU (time-of-check-time-of-use) race condition inSqlConnection.TryOpenInner().Where it crashes
In
SqlConnection.csline 2228:The race
Open()→TryOpenInner()→TryOpenConnection()completes successfully, setting_innerConnectionto a validSqlConnectionInternal.Open()(or another state-changing operation) on the sameSqlConnectioninstance, setting_innerConnectiontoDbConnectionClosedConnecting(a singleton transitional state marker).InnerConnectionfor the cast — but now it'sDbConnectionClosedConnecting, which is not assignable toSqlConnectionInternal→InvalidCastException.The key issue is that
_innerConnectionis read twice without synchronization: once forTryOpenConnection()and again for the cast. The field is modified via bothInterlocked.CompareExchange(inSetInnerConnectionFrom) and plain assignment (inSetInnerConnectionTo), so there is no consistent locking.Why it happens after idle / on startup
Open()calls on shared connection instancesMost likely user-side cause
SqlConnectionis not thread-safe. This exception almost always means the sameSqlConnectioninstance is being used from multiple threads simultaneously. Common causes in ASP.NET Core:SqlConnectionregistered as Singleton in DI (should be Scoped or Transient)SqlConnectionfield shared across requestsawaiton async operations, causing overlapping operations on the same connectionRecommendation
Immediate fix: Ensure each database operation creates its own
SqlConnection:Library-side improvement
The
TryOpenInnermethod could be hardened to detect this state and throw a more descriptive error (e.g., "Connection state changed unexpectedly. SqlConnection is not thread-safe — do not share instances across threads.") instead of the opaqueInvalidCastException.Could you confirm:
SqlConnectioncreated/managed? (DI registration? static field? per-request?)Microsoft.Data.SqlClientare you using? (The stack trace referencesSqlInternalConnectionTdswhich has been renamed toSqlConnectionInternalin recent versions.)Draft PR with reproducing tests: #4179
mrvogiacu commentedon Apr 12, 2026
hi @paulmedynski,
When I got this exception:
Microsoft.Data.SqlClientversion is 6.0.2What I've done to fix this exception:
Instead of using Sql instance with the Singleton scope, my DA class (DI with Scoped scope) inherits the Sql class and creates a Sql instance for each request.
Add tests confirming InvalidCastException race in TryOpenInner (#3314)
Fix TryOpenInner InvalidCast race and add unit regression tests (#3314)…
Fix TryOpenInner InvalidCast race and add unit regression tests (#3314)…