0X000002E8

Fix ERROR_RXACT_COMMITTED (0X000002E8) in SQL Server

Database Errors Intermediate 👁 0 views 📅 May 26, 2026

This error means a transaction already committed but something still references it. Here's how to stop it from wrecking your queries.

What's actually happening here

ERROR_RXACT_COMMITTED (0X000002E8) is SQL Server telling you a transaction has already committed—but some component hasn't noticed. The transaction log shows it's done, yet the session still holds a reference. This usually rears its head when you're using distributed transactions (DTC) or when application code doesn't properly check XACT_STATE() after a commit attempt.

I've seen this on SQL Server 2019 most often, especially with linked servers or when an ORM like Entity Framework manages transactions sloppily. The error message alone won't tell you which query triggered it—you'll need to trace it.

The 30-second fix: kill the stuck session

If this just happened and you need it gone fast, find the session ID (SPID) that's holding the ghost. Run this:

SELECT session_id, status, open_transaction_count
FROM sys.dm_exec_sessions
WHERE open_transaction_count > 0
  AND session_id > 50;

That gives you the open transactions. If you see one that's been hanging for minutes, kill it:

KILL {session_id};

The reason this works: killing the session forces SQL Server to clean up any lingering transaction references. It's a hammer, not a scalpel, but it gets your database moving again. You'll lose any uncommitted work in that session, but since the error says the transaction committed, you shouldn't lose data—just the session's local state.

After the kill, always check with DBCC OPENTRAN to verify no orphaned transactions remain:

DBCC OPENTRAN;

If it returns nothing, you're clean.

The 5-minute fix: check for DTC issues

If killing sessions doesn't stick—or the error keeps coming back—you've got a DTC problem. ERROR_RXACT_COMMITTED often means the MSDTC (Microsoft Distributed Transaction Coordinator) thinks the transaction is still pending. Here's how to check:

  1. Open Component Services (run dcomcnfg).
  2. Navigate to Component Services > Computers > My Computer > Distributed Transaction Coordinator > Local DTC.
  3. Right-click and choose Properties.
  4. On the Tracing tab, enable Transaction Manager Tracing to log what's happening.
  5. Check the Transaction List tab for any stuck transactions. If you see one, right-click and choose Resolve.

If you can't resolve it through the UI, you can force a DTC cleanup via the command line—but only do this on a test server first. Run this as admin:

net stop msdtc
msdtc -resetlog
net start msdtc

Resetting the log wipes DTC's transaction history. That's drastic. Only do it if you're certain no other distributed transactions are in flight. Otherwise you'll corrupt something.

A more surgical approach: restart only the SQL Server service after killing the problematic session. That flushes SQL's connection pool without touching DTC's log.

-- In SSMS, after killing the session:
SHUTDOWN WITH NOWAIT;

Then start SQL Server again. This resets all sessions and forces any leftover transaction references to die.

The 15+ minute fix: fix the application code

If this error is recurring, your application code is the root cause. The pattern I've seen: a .NET application using TransactionScope in a way that doesn't handle nested or distributed transactions correctly.

Here's the classic mistake:

using (var scope = new TransactionScope())
{
    // Do work...
    scope.Complete(); // This commits
    // Then some code after Complete() that throws
    // The scope disposes and thinks it needs to rollback,
    // but the transaction already committed.
}

What's actually happening: Complete() marks the transaction as committed, but if code after it throws an exception, the Dispose() method tries to roll back. SQL Server sees the rollback attempt on an already-committed transaction and throws ERROR_RXACT_COMMITTED.

The fix: never put code after Complete() that could throw. Or wrap the whole thing in a try-catch:

using (var scope = new TransactionScope())
{
    try
    {
        // Do work...
        scope.Complete();
    }
    catch
    {
        // Don't call scope.Complete() in catch.
        // Dispose will handle rollback properly.
        throw;
    }
}

If you're not using .NET, check your transaction management library. The principle is the same: once you commit, don't attempt any transaction-scoped cleanup afterward.

Another common trigger: sp_reset_connection in connection pooling. When a connection returns to the pool, SQL Server rolls back any open transactions. But if the transaction already committed, this rollback fires RXACT_COMMITTED. To fix this in your connection string, set Enlist=false to prevent automatic transaction enlistment:

Server=myServer;Database=myDB;Enlist=false;

That stops the connection from joining distributed transactions automatically. Do this if you're not actually using distributed transactions—many apps just don't need them.

When all else fails

If you've killed sessions, reset DTC, and fixed your code—and the error still appears—you might have a bug in SQL Server itself. I've seen this on SQL Server 2016 SP2 CU3. Check your version with SELECT @@VERSION. Microsoft released a hotfix for this exact error in later cumulative updates. Upgrade to the latest CU for your SQL Server version. That's your last resort, but it works.

If you can't upgrade, a workaround: disable automatic transaction enlistment entirely via a server-side trace flag. Don't do this unless you've tested it. Run DBCC TRACEON(1236, -1)—but consult Microsoft docs first. This flag changes how DTC handles transactions and can break things.

Was this solution helpful?