Quick Answer
Close the database connection, roll back any open transactions, reopen the connection, and retry the query.
Why This Happens
I've seen ERROR_CURRENT_TRANSACTION_NOT_VALID (0X00001A3A) pop up in SQL Server environments where a client holds a transaction open too long. The server eventually kills the transaction context, leaving the client hanging with a dead session. It's not a random glitch — it means the transaction you're trying to use doesn't exist anymore on the server side.
Most common scenario: a script opens a transaction, does some work, then hits a timeout or network blip. The server rolls back that transaction behind the scenes, but your client app still thinks it's alive. When you try to commit, you get this error. Had a client last month whose overnight batch job failed because a stored procedure left a transaction open after an index rebuild failed. The whole queue stalled until we killed the session manually.
Step-by-Step Fix
- Check for open transactions in your session.
Run this query to see if your session has a dangling transaction:
SELECT @@TRANCOUNT AS OpenTransactionCount;
If it returns 1 or more, you have an open transaction.
- Roll back the stale transaction.
Execute:
ROLLBACK TRANSACTION;
This clears the orphan. If you get another error here, skip to step 4.
- Close and reopen the connection.
In your app, close the database connection and open a fresh one. In SSMS, just disconnect and reconnect. - Kill the session (if rollback fails).
If the transaction won't rollback, find the session ID of your connection using:
SELECT @@SPID AS SessionID;
Then kill it from a separate SSMS window (with admin rights):
KILL <SessionID>;
Replace <SessionID> with the actual number.
- Reconnect and retry your query.
Open a new connection, start a fresh transaction, and run your original query again.
Alternative Fixes
Fix 1: Increase command timeout
If the error happens during long-running queries, bump up your command timeout in the connection string. For SQL Server, add Connection Timeout=300 (5 minutes). In ODBC, set QueryTimeout=300. This gives the server time to finish before killing the transaction.
Fix 2: Use explicit transaction retry logic
Wrap your transaction in a try-catch block with retry. Here's a T-SQL pattern:
DECLARE @retryCount INT = 0;
WHILE @retryCount < 3
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
-- your query here
COMMIT TRANSACTION;
SET @retryCount = 3;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
SET @retryCount = @retryCount + 1;
WAITFOR DELAY '00:00:01';
END CATCH
END;
Fix 3: Check connection pooling (SQL Server)
Connection pooling can recycle stale transactions. If you're using ADO.NET, set Pooling=False in your connection string as a temporary test. If the error goes away, you've got a pool corruption. Then enable pooling again but adjust the lifetime:
Server=myServer;Database=myDB;Pooling=True;Max Pool Size=50;Connection Lifetime=300;
Prevention
You can't avoid every timeout, but you can cut down these errors:
- Always close transactions. Use
COMMITorROLLBACKin every code path — no exceptions. - Set a transaction timeout. In SQL Server, use
SET LOCK_TIMEOUT 5000to fail fast instead of hanging. - Monitor long-running queries. Use
sys.dm_tran_active_transactionsto spot orphaned transactions before they cause errors. - Test network stability. A flaky wireless connection can drop transactions mid-flight. For production apps, use wired connections or retry logic.
One last thing: if you're using Entity Framework or similar ORM, make sure your context is disposed after each unit of work. I've seen apps leave database contexts open across HTTP requests, and that's a recipe for this exact error.