What’s happening here?
You’re seeing XACT_E_REENLISTTIMEOUT (0X8004D01E) when a distributed transaction tries to reenlist a resource manager — usually SQL Server or a transactional queue. The resource manager took too long to respond to MSDTC’s request to confirm the transaction status. I know this error is infuriating because it stops batch jobs dead, and the error message gives you almost nothing to work with.
Common scenario: You’re running a cross-database transaction between two SQL Server instances on separate machines, or using a transactional message queue like MSMQ. The transaction starts fine but hangs or fails during the second phase — the commit. The resource manager has 120 seconds by default to reenlist. If it misses that window, you get this error.
Let’s fix it. Try these in order — stop when the problem’s gone.
Fix 1: Restart MSDTC (30 seconds)
Quickest thing you can try. MSDTC gets stuck sometimes, especially after a long-running transaction or a network blip. Restarting clears its internal state and resets any stale reenlistment timers.
- Open Command Prompt as Administrator.
- Run these three commands:
net stop msdtc
net start msdtc
taskkill /f /im msdtc.exe 2>nul
Yes, the taskkill line is belt-and-suspenders. I’ve seen msdtc.exe linger in the background after a stop. Run it anyway.
Then retry your transaction. If it works, you’re done. If not, move on.
Fix 2: Increase the Reenlistment Timeout (5 minutes)
The default timeout is 120 seconds, but some operations — like large SQL Server transactions with lots of locks — can take longer. You can bump it up via the registry. I’d set it to 300 seconds (5 minutes) first. Anything much higher and you’re masking a real performance problem.
- Open Registry Editor (
regedit). - Navigate to
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC. - Right-click on the
MSDTCkey, choose New → DWORD (32-bit) Value. - Name it
ReenlistTimeout. - Double-click it, set the value to
300(decimal). That’s 300 seconds. - Restart MSDTC again (Fix 1 steps).
If you still get the error after this, the problem isn’t the timeout duration — it’s something else preventing the resource manager from responding at all.
Fix 3: Check Firewall and Network DTC Settings (15+ minutes)
Now we’re getting into the deep end. This error often shows up when the DTC can’t reach the remote resource manager because of firewall rules or misconfigured DTC security. Let’s verify both.
Step 3a: Open the right firewall ports
MSDTC uses a dynamic port range by default (RPC). That’s a headache for firewalls. If you can, pin DTC to a fixed port — it makes firewall rules simpler.
- Open Registry Editor.
- Go to
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC. - Create a DWORD named
ServerTcpPort, set it to3372(or any unused port above 1024). - Restart MSDTC.
Then on each machine (both the coordinator and the resource manager), open that port in Windows Firewall:
netsh advfirewall firewall add rule name="MSDTC Fixed Port" dir=in action=allow protocol=TCP localport=3372
Also make sure RPC Endpoint Mapper (port 135) is open inbound — DTC uses it to negotiate the connection.
Step 3b: Configure Network DTC Security
In Component Services (search for dcomcnfg), expand Component Services → Computers → My Computer → Distributed Transaction Coordinator. Right-click Local DTC and choose Properties.
Go to the Security tab. For most environments, check these:
- Network DTC Access — on
- Allow Inbound — on
- Allow Outbound — on
- Mutual Authentication Required — on (unless you’re in a workgroup; then use “No Authentication Required” but that’s less secure)
- Enable Transaction Internet Protocol (TIP) Transaction Manager Communication — only if you’re using TIP (rare). Leave off otherwise.
Apply, restart MSDTC, test again.
One last thing: Check the Application Event Log
If none of these fixes work, look in Event Viewer → Applications and Services Logs → Microsoft → Windows → MSDTC → Operational. There’s a specific event ID 4370 that logs the actual reason for the reenlistment failure. It might say “resource manager is not available” (network issue) or “transaction already committed” (logic bug in your app). That event gives you the real answer.
If you’re still stuck after all this, the problem is likely in your application code — you’re trying to reenlist a transaction that’s already resolved. Double-check your transaction logic. I’ve seen that more times than I’d like to admit.