0X8004D006

XACT_E_HEURISTICDAMAGE (0X8004D006): What It Means and How to Fix It

XACT_E_HEURISTICDAMAGE hits when transaction services can't agree. Here's why it happens and how to fix it without pulling your hair out.

Had a client last month running a custom .NET app that talks to SQL Server and a message queue. Every few days, one user's order would just… vanish. No error in the app log, no error on the SQL side, nothing. Turned out the app was logging 0X8004D006 at the DEBUG level, which nobody was looking at. That's XACT_E_HEURISTICDAMAGE, and it's one of those errors that stays quiet until it bites you.

The trigger is almost always the same: a distributed transaction spanning more than one resource manager (SQL Server, MSMQ, Oracle, whatever) where one resource commits and the other doesn't. The transaction coordinator throws up its hands and says "I don't know what state this is in anymore." That's the heuristic damage part.

What XACT_E_HEURISTICDAMAGE Actually Means

In distributed transaction land, you have a two-phase commit. Phase one: everyone says "yeah I'm ready." Phase two: everyone commits. When it works, it's beautiful. When it doesn't, you get XACT_E_HEURISTICDAMAGE.

Heuristic damage happens when the transaction manager has lost confidence that the resources are in a consistent state. Say resource A committed and resource B rolled back. From Windows' point of view, that's not a clean failure — it's a mess. The transaction is broken in a way it can't automatically resolve, so it stamps the error and moves on.

I've seen this most often after network hiccups between web servers and database servers, or after someone reboots a SQL box in the middle of a batch job. The transaction coordinator is still on the network, but one of the resource managers has already made a decision on its own.

Common Triggers

  • MSDTC (Distributed Transaction Coordinator) service restarting mid-transaction
  • Network timeout between the app server and SQL Server
  • Firewall blocking RPC ports that MSDTC needs
  • Mixed transaction outcomes — one resource commits, one aborts
  • Running under an account that doesn't have permission to talk to MSDTC

The Fix

Start with the boring stuff. Most of the time this error clears up once MSDTC is healthy and everyone can talk to it.

  1. Restart MSDTC on every machine in the chain. Not just the app server — the database server too. Open an admin command prompt and run:
    net stop msdtc
    net start msdtc
    Yes, this drops in-flight transactions. That's fine. Any transaction in heuristic damage state is already toast.
  2. Check the MSDTC configuration. Open dcomcnfg from Run. Navigate to Component Services > Computers > My Computer > Distributed Transaction Coordinator > Local DTC. Right-click, Properties. On the Security tab, these should be set:
    • Network DTC Access: checked
    • Allow Remote Clients: checked
    • Allow Inbound: checked
    • Allow Outbound: checked
    • Incoming Caller Authentication Required: checked
    • Mutual Authentication Required: needs to match on both sides (both on or both off)
    If you change anything, MSDTC will prompt to restart. Let it.
  3. Verify the firewall. If you're on Windows Server 2016 or later with the default firewall, MSDTC needs specific rules. Open an elevated PowerShell and allow the built-in group:
    netsh advfirewall firewall set rule group="Distributed Transaction Coordinator" new enable=yes
    Also make sure RPC dynamic ports are open between the machines — MSDTC still leans on RPC endpoint mapper (port 135) and a dynamic range.
  4. Ping each server by NetBIOS name. MSDTC is picky. If it can't resolve the other machine by name, it'll fail. From the app server:
    ping SQLSERVER01
    net view \\SQLSERVER01
    If either fails, fix DNS or hosts file first. Skip this step at your peril — I've wasted hours on MSDTC settings when the actual problem was a stale DNS record.
  5. Test with DTCTester. Microsoft ships a small utility called DTCTester that runs a fake distributed transaction against a SQL Server. If that passes, MSDTC is healthy. If it fails, you've narrowed it down. Grab it from the Windows SDK and run:
    dtctester sqlserver01 dbname username password
  6. Look for orphaned transactions. Sometimes a transaction is stuck in the coordinator. Open Component Services, drill into Transaction Statistics and Transaction List. If you see a transaction sitting in "In Doubt" for hours, that's your problem child. Right-click and resolve it — commit or abort, pick one — then restart MSDTC.

If It Still Fails

Check the event logs. You want Application and System logs on both the app server and database server. Filter for source MSDTC or Microsoft-Windows-MSDTC. If you see 53258 or 4104 events, the transaction coordinator is telling you exactly which resource is unresponsive.

Also check whether your application is actually catching the exception. A surprising number of apps log this at DEBUG and move on. If the app is treating heuristic damage as a soft failure, you might be seeing data inconsistency downstream that has nothing to do with MSDTC at all. Wrap your transaction commit in a try/catch and bubble the error up.

And if you're on a VM with snapshot-based backups — yes, this is a real thing — MSDTC can get confused after a restore. The transaction IDs on disk don't match what the coordinator remembers. Restart MSDTC, clear the log, and you're usually fine. Had a client whose backup vendor was snapshotting SQL without letting MSDTC quiesce, and they hit this every single night. Took a week to figure out, and the fix was one line in the backup job.

Related Errors in Windows Errors
0XC00D1132 NS_E_WMPBR_RESTORECANCEL (0XC00D1132) — Rights Restoration Canceled Fix 0XC01A0025 STATUS_LOG_CLIENT_NOT_REGISTERED (0xC01A0025) Fix 0X401E043A Fix STATUS_GRAPHICS_START_DEFERRED 0x401E043A 0XC0000908 STATUS_BAD_MCFG_TABLE (0XC0000908) — The PCI resource conflict fix

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.