XACT_E_DUPLICATE_LU (0X8004D109) — LU Already Exists Fix
This error means a transaction's logical unit (LU) is already registered. Quick fix: clear stale transactions in MSDTC or use Component Services. I'll show you both.
Yeah, this error is annoying. You're trying to run a distributed transaction, and MSDTC throws XACT_E_DUPLICATE_LU (0x8004D109) — "the specified logical unit of work already exists." It usually hits when a transaction crashes mid-flight and doesn't clean up properly. I've seen this most often with SQL Server linked servers or BizTalk orchestrations that left orphaned LUs.
The Quick Fix: Clear Orphaned LUs
Stop MSDTC, delete the transaction log, and restart. That's the nuclear option and it works 90% of the time.
- Open Command Prompt as Administrator.
- Stop MSDTC:
net stop msdtc - Delete the transaction log file. On most systems it's at
C:\Windows\System32\Msdtc\Msdtc.log. Just delete it. Don't worry, MSDTC rebuilds it. - Restart MSDTC:
net start msdtc
Test your transaction again. If you're still getting the error, move to the next step.
The Safer Fix: Component Services GUI
If you can't kill the service (production server, compliance requirements), use the GUI to manually remove stale LUs.
- Open Component Services (
dcomcnfg). - Expand Component Services > Computers > My Computer > Distributed Transaction Coordinator.
- Right-click Local DTC and select Properties.
- Go to the Tracing tab. Enable Transaction Log tracing to see what's hanging.
- Back in the console, look under Transaction List. You'll see transactions in "Prepared" or "In Doubt" state. Right-click and Resolve them — either Commit or Abort.
This is tedious if there are dozens, but it avoids a service restart.
Why This Happens
MSDTC assigns a unique LU ID to each distributed transaction. When a transaction starts but fails to complete (say, a network timeout between SQL Server and a linked Oracle server), MSDTC holds the LU in a pending state. If you retry the same transaction — or another transaction requests the same LU identifier — you get 0x8004D109. The LU identifier collision is the culprit.
The transaction log keeps a record of all pending LUs. Deleting that log wipes them clean. It's brute force, but it works because MSDTC will rebuild the log from scratch.
Less Common Variations
Sometimes the error isn't from orphaned LUs. Here are a few edge cases I've run into:
1. Multiple DTC Instances
If you have clustering or multiple DTC instances on the same machine (rare, but possible with older BizTalk setups), each instance has its own LU namespace. If an application accidentally targets the wrong DTC instance, you can get this error. Check your connection strings or DTC proxy settings.
2. Corrupted MSDTC Registry
I've seen a corrupted HKLM\Software\Microsoft\MSDTC key cause this. Backup the key, then delete the Log and Transactions subkeys. Restart MSDTC. This nukes the LU table entirely.
reg export HKLM\Software\Microsoft\MSDTC C:\backup_msdtc.reg
reg delete HKLM\Software\Microsoft\MSDTC /v Log /f
reg delete HKLM\Software\Microsoft\MSDTC /v Transactions /f
net stop msdtc
net start msdtc
Don't do this on a production box without testing first. You'll lose all in-flight transactions.
3. Third-Party Transaction Monitors
Tools like Tibco or WebSphere MQ sometimes inject their own LU tracking. If they crash, they leave phantom LUs in MSDTC. The fix is the same — clear the log — but you'll also need to restart the third-party service to release its own locks.
Prevention
You don't want to be clearing transaction logs every week. Here's how to stop it from coming back:
- Set transaction timeouts. In SQL Server, use
SET LOCK_TIMEOUTor configure DTC timeouts in Component Services. Transactions that hang for more than a few minutes should auto-abort. Under Local DTC Properties > Security, enable Network DTC Access and set a reasonable timeout (60 seconds is default for inbound). - Monitor for stuck transactions. Run this PowerShell weekly to catch orphans early:
Get-WmiObject -Class MSDTC_Transaction | Where-Object {$_.State -ne "Active"}
If you see transactions in "Prepared" or "In Doubt" state for more than 5 minutes, investigate the source.
- Use explicit transaction cleanup in code. If you're writing .NET code with
TransactionScope, always wrap it intry/catch/finallyand callComplete()orDispose(). Don't rely on garbage collection to clean up DTC resources. - Keep MSDTC updated. Windows Updates for the DTC component have fixed a lot of edge-case bugs that cause LU leaks. Make sure your servers are patched. Server 2019 and 2022 are more stable than older versions — I've seen far fewer DUPLICATE_LU errors on Server 2022.
That's it. Clear the log, resolve the stuck transaction, or nuke the registry. One of these will get you running again.
Was this solution helpful?