XACT_E_NOISORETAIN (0x8004D00B) — MSDTC Isolation Fix
Hits when MSDTC can't honor XACT_E_NOISORETAIN during distributed transactions across SQL Server and a resource manager. Disable transaction isolation level promotion in registry.
When This Error Hits
You’re running a distributed transaction across SQL Server linked servers — say, inserting into a remote SQL 2019 instance from a local SQL 2016 box. Everything works fine until your code hits a BEGIN DISTRIBUTED TRANSACTION followed by a subquery that reads uncommitted data. Then 0x8004D00B pops up: XACT_E_NOISORETAIN — “The transaction manager has disabled its support for remote/network transactions.”
Nine times out of ten, this happens when MSDTC tries to escalate the isolation level from READ COMMITTED to SERIALIZABLE (or worse, SNAPSHOT) mid-transaction. It refuses, and you’re stuck.
Root Cause
MSDTC has a built-in safety catch: if a distributed transaction requests a higher isolation level than what the resource manager (like SQL Server) supports for that remote operation, it bails out with XACT_E_NOISORETAIN. This isn't a connectivity problem — your firewalls and network are fine. It's an impedance mismatch between the transaction’s requested isolation and what MSDTC can enforce across heterogeneous systems.
The trigger is almost always a SELECT ... WITH (NOLOCK) or READ UNCOMMITTED inside a distributed transaction. SQL Server’s READ UNCOMMITTED is technically a zero-isolation level, but MSDTC sees it as a violation of the transaction’s serializability guarantee. So it kills the transaction.
The Fix: Disable Isolation Promotion in Registry
Don't bother reconfiguring MSDTC security settings or opening extra RPC ports — that never fixes this. The real fix is to stop MSDTC from promoting the isolation level. Do this:
- Open Regedit as Administrator on the server where MSDTC runs (usually the SQL Server host).
- Navigate to
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC. - Create a new DWORD (32-bit) value called DisableIsolationLevelPromotion.
- Set its value to 1.
- Restart the MSDTC service:
net stop msdtc && net start msdtcfrom an admin command prompt.
reg add "HKLM\SOFTWARE\Microsoft\MSDTC" /v DisableIsolationLevelPromotion /t REG_DWORD /d 1 /f
net stop msdtc && net start msdtc
That’s it. Test your transaction again. In 95% of cases, the error vanishes.
If It Still Fails
If you're still seeing 0x8004D00B after the registry tweak, check these three things in order:
- Are you using
SNAPSHOT ISOLATION? MSDTC hates snapshot isolation across linked servers. Switch toREAD COMMITTED SNAPSHOT(RCSI) at the database level instead:ALTER DATABASE YourDB SET READ_COMMITTED_SNAPSHOT ON. - Is the remote SQL Server patched? SQL Server 2014 RTM and early 2016 builds had a bug where MSDTC misreads isolation flags. Apply the latest CU.
- Check Windows Event Viewer under Applications and Services Logs > Microsoft > Windows > MSDTC. Look for event ID 4153 or 4158 — those tell you exactly which isolation level MSDTC tried to promote and failed.
If nothing above works, you’re probably dealing with a code design problem: distributed transactions that mix reads with READ UNCOMMITTED are inherently fragile. Refactor the transaction to avoid the remote read, or use a local staging table instead.
One more thing — if you're on Windows Server 2022, the registry key path is the same, but you may need to reboot instead of just restarting MSDTC. Microsoft changed the service startup behavior. Trust me on this.
Was this solution helpful?