0X8004D022

XACT_E_DEST_TMNOTAVAILABLE (0X8004D022) Fix

Database Errors Intermediate 👁 1 views 📅 May 29, 2026

This happens when a distributed transaction can't reach the MSDTC service on the target server. It's usually a firewall or network name resolution issue.

Quick answer

Enable inbound DTC traffic in Windows Firewall on the destination machine, then restart the MSDTC service. If that doesn't work, check that the destination server name resolves to the correct IP and the RPC service is running.

What's actually happening here

This error fires when your application kicks off a distributed transaction—say, a SQL Server linked server query that spans two servers—and the transaction manager on the target box (the destination) won't cooperate. The MSDTC (Microsoft Distributed Transaction Coordinator) on the source machine tries to contact the MSDTC on the destination using RPC over port 135, then negotiates a dynamic port range (typically 49152–65535 on modern Windows). If that handshake fails at any point—firewall blocks the RPC endpoint, the destination machine's name doesn't resolve correctly, or the MSDTC service itself is stopped—you get 0x8004D022.

I see this most often in SQL Server environments where a linked server runs a cross-server query. The trigger is usually a SELECT * FROM [ServerB].[Database].[Schema].[Table] that works fine for single-row fetches but blows up when the query writes back or runs in a transaction scope. Another common scenario: a .NET application using TransactionScope against two different databases.

Fix steps

  1. Enable inbound DTC in Windows Firewall on the destination machine. On Windows Server 2016/2019/2022 or Windows 10/11, open wf.msc as admin. Go to Inbound Rules, find the three rules named Distributed Transaction Coordinator (RPC), Distributed Transaction Coordinator (RPC-EPMAP), and Distributed Transaction Coordinator (TCP). Enable all three. If they don't exist, create them manually by adding port 135 for RPC-EPMAP and a static port range for DTC transactions (I'd pick 50000-50200 to keep it predictable). Then restart MSDTC:
    net stop msdtc
    net start msdtc
  2. Verify network name resolution. On the source machine, ping the destination server name. If it resolves to the wrong IP or fails entirely, check DNS or your hosts file. The transaction manager uses the server name, not the IP, so a mismatch here breaks the handshake silently. Run nslookup DestinationServerName to confirm.
  3. Check MSDTC service state on the destination. On the destination, run services.msc, find Distributed Transaction Coordinator, and make sure it's running with startup type set to Automatic. If it's stopped, start it. If it's running but acting flaky, stop and restart it from the command line: net stop msdtc && net start msdtc.
  4. Configure DCOM settings for MSDTC. If the firewall and service are fine, the issue might be DCOM permissions. Open dcomcnfg, expand Component Services -> Computers -> My Computer. Right-click My Computer, choose Properties, go to COM Security, and ensure Everyone has Remote Access and Remote Launch permissions under both Access Permissions and Launch and Activation Permissions. Apply and reboot.
  5. Enable network DTC access explicitly. On the destination, open dcomcnfg, go to Component Services -> Computers -> My Computer -> Distributed Transaction Coordinator -> Local DTC. Right-click Local DTC, choose Properties. On the Security tab, check Network DTC Access, Allow Inbound, and Allow Outbound. Also check No Authentication Required if you trust the network (this avoids Kerberos double-hop issues in Windows domains). Click OK and restart MSDTC.

Alternative fixes if the main one fails

If the above steps don't cut it, try these:

  • Set a static DTC port range. Open Registry Editor on the destination, navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC. Create a DWORD named ServerTcpPort and set it to a decimal value like 50000. Then open Windows Firewall, add an inbound rule for TCP port 50000, and restart MSDTC. This forces DTC to use a single port instead of the dynamic range, making firewall rules dead simple.
  • Check RPC service availability. The RPC Endpoint Mapper runs on port 135. If that service is disabled or blocked, MSDTC can't even start the handshake. On both machines, run services.msc and verify Remote Procedure Call (RPC) and RPC Endpoint Mapper are running and set to Automatic.
  • Temporarily disable the firewall for testing. On the destination, turn off the Windows Firewall (or any third-party firewall) just long enough to test the transaction. If the error goes away, you know it's a firewall config issue. Turn it back on and refine the rules.
  • Check third-party antivirus. Some antivirus suites, especially McAfee and Symantec, have their own firewall modules that block DTC traffic. Disable them temporarily or add an exception for the MSDTC process (msdtc.exe).

Prevention tip

Set up a static DTC port range and corresponding firewall rule on every server that participates in distributed transactions. Do this before you ever run into the error. It's a five-minute config that saves you hours of head-scratching later. Document the port range in your server build docs, and standardize it across all machines—pick something like 50000-50200 to stay out of the way of other services.

One more thing: if you're using SQL Server, you can bypass distributed transactions entirely by using OPENQUERY or OPENROWSET with a four-part name that doesn't trigger a distributed transaction—but that's a band-aid, not a fix. The real fix is making MSDTC work right.

Was this solution helpful?