XACT_E_NOTSINGLEPHASE (0x8004D103): Fix for MSDTC single-phase error
This error means a distributed transaction tried to do a single-phase commit but couldn't. The fix is to disable network DTC access or reconfigure the transaction coordinator.
Yeah, that 0x8004D103 error is a pain. It pops up when you're doing something like running a stored procedure across two databases or using COM+ transactions, and suddenly everything stops. Let's kill it fast.
The quick fix: Disable network DTC access
What's actually happening here is the MSDTC (Microsoft Distributed Transaction Coordinator) is trying to use a single-phase commit optimization when it shouldn't. The simplest fix for most people is to turn off network DTC entirely — most apps don't need it.
- Open Component Services (run
dcomcnfgfrom Start menu). - Go to Component Services > Computers > My Computer > Distributed Transaction Coordinator.
- Right-click Local DTC and select Properties.
- Go to the Security tab.
- Uncheck Network DTC Access.
- Click OK and restart the DTC service (
net stop msdtc && net start msdtcas admin in Command Prompt).
After that, try your transaction again. If it works, you're done. The reason step 5 works is that without network access, MSDTC can't even try the single-phase optimization — it forces a full two-phase commit, which is what the transaction actually needed.
Why this error happens
The error text says it all: "The prepare request given was not eligible for single-phase optimizations." In plain English: MSDTC thought it could shortcut the commit process (single phase), but the transaction involved multiple resources (like two databases or a database and a file system) that required a full two-phase commit.
This happens when:
- You have network DTC enabled but the remote machine isn't configured right.
- The transaction spans more than one resource manager (SQL Server, MSMQ, file system).
- An older app or piece of code explicitly requests single-phase but can't handle it.
The error code 0x8004D103 is the NT status for XACT_E_NOTSINGLEPHASE. It's a COM+ error, not a SQL Server one, so don't waste time checking your SQL logs first — check DTC.
Less common variations of the same issue
1. SQL Server linked server transactions
If you're running a distributed query between two SQL instances and getting this error, the fix often isn't disabling network DTC — it's enabling Inbound and Outbound with Allow Remote Clients on both machines. Then set the DTC authentication to Mutual Authentication Required.
2. COM+ components in IIS
If you're hosting a COM+ component in IIS and get this error, check the component's transaction settings. Right-click the component in Component Services, go to Properties > Transactions, and set Transaction support to Requires a Transaction instead of Supports Transactions. The reason this matters is that "Supports" lets the component run outside a transaction — which then confuses MSDTC when it tries to optimize.
3. Firewall blocking DTC ports
MSDTC uses RPC dynamic ports (usually 1024-65535). If you have a strict firewall, you need to open ports 135 (RPC Endpoint Mapper) and configure a static port range for DTC. Run netstat -abn to see which port DTC is using, then open it in the firewall.
How to prevent this from coming back
Three things to set once:
- Keep network DTC off unless you really need it. Most apps that claim they need it actually don't — they just need local transaction support. Test without it first.
- If you must use network DTC, configure it correctly upfront. On both machines: enable Network DTC Access, Inbound, Outbound, and set Authentication to Mutual Authentication Required. Then add the remote machine's IP to the Windows hosts file to avoid DNS issues.
- Monitor DTC logs. Open Event Viewer > Applications and Services Logs > Microsoft > Windows > MSDTC. Look for events with ID 4109 or 4110 — those tell you exactly which resource manager is failing.
One last thing: if you're still getting the error after all this, check if your code is using TransactionScope with TransactionScopeOption.RequiresNew. That forces a new transaction, which can trigger the single-phase optimization bug on older .NET versions. Switch to Required instead. Or upgrade to .NET 8+, where they fixed this.
Was this solution helpful?