You're running a distributed transaction—say, a stored procedure on SQL Server 2019 that updates a database on another server via a linked server, or a C# app using TransactionScope against two different SQL instances. Suddenly you get XACT_E_LOGFULL (0x8004D01A) and the whole operation rolls back. This isn't a SQL Server database log issue. It's the Microsoft Distributed Transaction Coordinator (MSDTC) that has a separate transaction log, and that log just hit its maximum size. The error appears most often after a period of high volume with many long-running or uncommitted transactions, or after a server crash that left dozens of transactions in doubt.
What's actually happening here
MSDTC keeps a log (usually C:\Windows\System32\MSDTC\MSDTC.log) that records every distributed transaction's state: prepared, committed, aborted, in-doubt. This log is what allows MSDTC to coordinate recovery if any participant goes down mid-transaction. The log is not infinite—by default it can grow, but it has a hard cap (often 64 MB, configurable up to 256 MB). When the log fills, MSDTC refuses new transactions and throws XACT_E_LOGFULL. The key thing to understand: the log doesn't automatically truncate entries for transactions that are still open or in doubt. So if your app opens a distributed transaction and never commits or rolls back—say, because a connection pool holds a transaction open, or a TransactionScope isn't disposed properly—those entries accumulate. Enough of those and the log hits the ceiling.
The common trigger isn't a single huge transaction. It's a slow leak: a service that opens a transaction and then blocks on a network call, or a poorly written retry loop that reuses a transaction object without resetting it. Over days, the log fills. Then even a tiny two-phase commit fails.
The fix: clear the MSDTC log
You need to stop MSDTC, delete or truncate the log, and restart. But don't skip the cleanup steps—just deleting the log without handling in-doubt transactions can leave your databases with unresolved distributed transactions.
- Stop MSDTC. Open an elevated command prompt and run:
net stop msdtc - Find the log file. It's typically at
C:\Windows\System32\MSDTC\MSDTC.log. Check the path withdir C:\Windows\System32\MSDTC. If it's elsewhere, you can query the registry atHKEY_LOCAL_MACHINE\Software\Microsoft\MSDTC—look forLogPath. - Rename (don't delete yet) the log to
MSDTC.log.old. That way, if anything goes wrong you can restore it. Run:rename C:\Windows\System32\MSDTC\MSDTC.log MSDTC.log.old - Restart MSDTC. It will create a fresh, empty log.
net start msdtc - Resolve any in-doubt transactions. On each SQL Server involved, run
SELECT * FROM sys.dm_tran_active_transactions(orDBCC OPENTRANfor the database). Look for transactions withstatus = 1(uncommitted) and a long duration. If you find any, you can commit or roll them back manually. You'll often see aDT_Xprefix in the transaction name, which means it's a distributed transaction.
The reason this works: MSDTC recreates the log from scratch, and once you clear the in-doubt entries, the new log stays small. If you skip step 5, the log might fill again quickly because the old in-doubt transactions get replayed during recovery.
If it still fails
If 0x8004D01A comes back after a short time, the log is filling again with new transactions. Here's what to check:
- Are there orphaned transactions? Use
SELECT * FROM sys.dm_tran_active_transactionson each SQL Server in the transaction. Look for transactions that have been open for hours. Those are your culprits. Kill the sessions causing them (KILL session_id), or fix the code that leaks them. - Is your application setting a timeout? If you're using
TransactionScope, set an explicitTransactionOptionswith aTimeoutlike 30 seconds. The default is 60 seconds but that can still leave entries if the transaction never completes due to a deadlock. Setting a timeout forces any stuck transaction to roll back, freeing log space. - Check the MSDTC log size limit. The default maximum is 256 MB (set by the registry value
MaxLogSizeunderHKLM\Software\Microsoft\MSDTC, in MB). If you have legitimate high throughput, you might need to raise it. But I'd argue that's a band-aid—fix the transaction leaks first. - Look for network issues. If a participant server is intermittently unreachable, prepared transactions sit in doubt until the connection recovers. That fills the log fast. Check for firewall changes or DNS issues between the servers.
One more thing: don't just delete the log while MSDTC is running. That can corrupt the transaction state and leave databases in recovery. Always stop the service first. And remember, this error is a symptom, not the disease. Clearing the log buys you time, but you have to find why transactions aren't completing. In my experience, it's almost always a missing TransactionScope.Complete() or a connection pool that's holding a transaction open. Fix that and you won't see this error again.