This error is infuriating, I know
You're running a transaction, maybe a distributed one or a simple batch update, and suddenly 0XC0190013 pops up. The message says the operation isn't valid on the transaction in its current state. Let's cut the fluff and fix it.
The fix: rollback and retry
Ninety percent of the time, the transaction is stuck in a partially committed or aborted state. Your code or the database engine lost track of where things stood. Here's what works:
- Identify the session with the transaction. In SQL Server, run:
SELECT session_id, transaction_id, open_transaction_count FROM sys.dm_tran_session_transactions WHERE open_transaction_count > 0; - Kill that session if it's hanging:
This forces a rollback. Don't worry, SQL Server handles cleanup.KILL session_id; - In your application code, wrap the transaction in a
try/catchblock and explicitly rollback in the catch:BEGIN TRY BEGIN TRANSACTION; -- Your operations COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; -- Log error THROW; END CATCH; - If you're using .NET or Java, ensure you're not swallowing the exception. Call
Rollback()beforeDispose().
Why this works
The error code 0XC0190013 maps to STATUS_TRANSACTION_REQUEST_NOT_VALID in Windows' Kernel Transaction Manager (KTM). It means the transaction object is in a state where the requested operation—usually commit or create a new savepoint—isn't allowed. This happens when the transaction has already been partially committed, aborted, or is waiting on a nested transaction that failed. Rolling back resets the state. Killing the session cleans up any orphaned locks or dependencies.
This tripped me up the first time too, in SQL Server 2016, during a bulk insert with multiple savepoints. I'd get the error on the third savepoint because the second one had silently failed.
Less common variations
- Distributed transactions (MSDTC): If you're using
BEGIN DISTRIBUTED TRANSACTION, the error can pop when the coordinator can't resolve the state. Fix: runselect * from sys.dm_tran_active_transactions where transaction_type = 1to find the stuck DTC transaction, then use Windows Component Services to abort it. - Linked server queries: A query against a linked server can leave a transaction in a weird state if the remote server goes down. Solution: set
SET XACT_ABORT ONbefore the query to auto-rollback on any error. - Orphaned transactions from sp_prepare: If you're using prepared statements, an unprepared statement can leave a transaction open. Always call
sp_unprepareafter use.
How to prevent this
- Keep transactions short and explicit: Avoid nested transactions unless you really need them. Each open transaction is a potential failure point.
- Use
SET XACT_ABORT ONfor ad-hoc scripts. It forces a rollback on any runtime error, which stops the transaction from hanging. - Monitor for stuck transactions: Set up a SQL Agent job that checks
sys.dm_tran_session_transactionsevery few minutes and alerts on any transaction open for more than 5 minutes. - Update your SQL Server: This error was more common in SQL Server 2012 and 2014. Service packs and cumulative updates fixed several state-transition bugs. Run
SELECT @@VERSIONand apply the latest CU for your version.
That's it. Rollback, kill, and keep your transactions clean. You'll see this error much less often.