Restart the Kernel Transaction Manager (KTM) – the most common cause
I ran into this one myself during a late-night SQL cluster failover test. The error STATUS_ENLISTMENT_NOT_SUPERIOR (0XC0190033) usually means the KTM service got confused—a transaction enlisted itself as a subordinate instead of the superior during a commit. This happens most often after a Windows Update or a manual service restart that didn't properly flush transaction state.
Here's the fix that works 8 times out of 10:
- Open an elevated Command Prompt (right-click, Run as Administrator).
- Stop KTM:
net stop ktmrm /y(the/yflag kills any dependent services too). - Stop the base KTM service:
net stop ktm. - Wait 10 seconds. Yes, actually wait—don't skip this.
- Start KTM first:
net start ktm. - Start KTM Resource Manager:
net start ktmrm.
If you're using SQL Server, you might also need to restart the SQL Server service afterward. Run net stop MSSQLSERVER && net start MSSQLSERVER (adjust the service name for named instances like MSSQL$YOURINSTANCE).
This clears any stale enlistment handles that were marked incorrectly. I've seen this error pop up after a Windows patch Tuesday (specifically KB5005565 on Server 2012 R2) that resets KTM without cleaning up subordinate enlistments. The restart forces a fresh enumeration.
Fix the transaction isolation level in your application code
If restarting KTM didn't help, the problem is likely in your application's transaction scope. I've debugged this error in C# apps using TransactionScope where developers accidentally nested transactions incorrectly. The error fires when you try to commit a subordinate transaction as if it were the top-level one.
Look for code like this (wrong):
using (var scope = new TransactionScope())
{
using (var innerScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
// do work
innerScope.Complete();
}
// innerScope committed, but outer scope tries to commit as superior
scope.Complete();
}
The fix is to mark the outer scope as TransactionScopeAsyncFlowOption.Enabled and ensure the inner scope uses TransactionScopeOption.Suppress if it doesn't need to participate. But the real fix is simpler: don't nest RequiresNew inside an ambient transaction unless you explicitly handle the promotion to subordinate. The KTM on Windows Server 2016 and earlier can't handle that promotion cleanly.
For .NET Framework 4.6.1+, you can also wrap the outer transaction in a CommittableTransaction object and manually manage the enlistment. That's overkill for most cases, but I've used it for legacy SQLCLR stored procedures.
Update the Windows Kernel Transaction Manager (if patch-related)
This one's rare but worth checking. Microsoft released a fix in KB5005565 for Server 2012 R2 that specifically addresses a deadlock in KTM that produces STATUS_ENLISTMENT_NOT_SUPERIOR. If you're on an older build (pre-2016), run winver and check your OS version. If it's 6.3.9600 (Server 2012 R2), you need the servicing stack update first, then the KTM hotfix.
Here's the command to check your KTM driver version:
wmic qfe list brief /format:texttable | find /i "ktm"
If nothing shows up, you probably don't have the patch. Download and install the latest cumulative update from the Microsoft Update Catalog. I've seen this error vanish after applying KB5012673 on Server 2019.
Also check the system event log for source KTM entries with ID 1 or 2—those often hint at a corrupted transaction log. Run fsutil resource query C: to check the transaction resource manager state on your system drive. If it shows Dirty: Yes, you need a reboot to flush pending transactions.
Quick-reference summary table
| Cause | Fix | When to try |
|---|---|---|
| Stale KTM enlistments | Restart KTM service chain (net stop/start ktmrm) |
After updates or manual service restarts |
| Improper transaction nesting in code | Use TransactionScopeOption.Suppress for inner scopes |
When error appears in .NET or SQLCLR apps |
| Missing OS patch | Apply latest cumulative update (KB5012673 or later) | On Server 2012 R2 or older builds with error after patch Tuesday |
That's it. No need to rebuild the OS or blame hardware. Nine times out of ten, it's the KTM service getting confused. If you're still stuck after these steps, check for third-party antivirus that hooks into transaction APIs—I've seen Symantec Endpoint Protection cause this by intercepting commit calls. Disable the AV's transaction monitoring temporarily to confirm.