0X8004D009

XACT_E_NOASYNC (0x8004D009): Fixes That Actually Work

XACT_E_NOASYNC means your app tried an async transaction call the MSDTC doesn't support. Here's the fast fix and the deeper causes you need to know.

If you're staring at XACT_E_NOASYNC (0x8004D009) right now, I get it. This error is infuriating because it fires mid-transaction, usually during a routine call, and the message doesn't tell you squat about what to change. I've seen this trip up devs working with .NET, Python, and even Java apps that touch MSDTC. The good news? The fix is usually straightforward once you know what's happening.

Cause #1: You're using async calls on a sync-only MSDTC API

This is the big one. XACT_E_NOASYNC literally means the transaction manager doesn't support an asynchronous operation for the method you called. In plain English: you're calling an async method that MSDTC doesn't have an async implementation for.

The most common trigger: You've got a .NET 4.x (or earlier) app using TransactionScope with an async database operation. Specifically, calling SqlCommand.ExecuteNonQueryAsync() inside a TransactionScope that's not marked with TransactionScopeAsyncFlowOption.Enabled. Before .NET 4.5.1, async operations inside a transaction scope didn't flow the ambient transaction to the async continuation, and MSDTC simply refused to play ball when you forced it.

The fix that works 90% of the time

  1. Make sure your app targets .NET 4.5.1 or later (ideally .NET 4.7.2+ for production).
  2. Create your TransactionScope with the async flow option:
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
    await someCommand.ExecuteNonQueryAsync();
    scope.Complete();
}

If you're not using TransactionScope but directly calling TransactionManager.Enlist or Transaction.EnlistVolatile, stop there. Those methods are synchronous-only. There's no async overload. If you need async, you restructure your code to do the async work first, then enlist, then commit synchronously.

Also, check if you're using a distributed transaction at all. Sometimes people end up with MSDTC because they have two connections to the same database open at once. If you don't need distributed transactions, close the extra connection. That'll sidestep MSDTC entirely.

Cause #2: MSDTC network access is misconfigured

Even with async flow enabled, you can still hit XACT_E_NOASYNC if MSDTC itself isn't set up for network transactions. This happens a lot in dev environments where someone turned on MSDTC client access but forgot the server side.

Real-world scenario: You're running a web app on one machine and SQL Server on another. Your code correctly uses TransactionScopeAsyncFlowOption.Enabled, but the moment the transaction escalates to a distributed one, you get the error. That's not an async problem; that's MSDTC refusing to coordinate because its network settings are wrong.

How to fix the MSDTC configuration

  1. On both the client and server machines, open Component Services (run dcomcnfg).
  2. Navigate to Component Services > Computers > My Computer > Distributed Transaction Coordinator.
  3. Right-click Local DTC, select Properties, then the Security tab.
  4. Check these boxes on both ends:
    • Network DTC Access
    • Allow Inbound
    • Allow Outbound
    • Enable XA Transactions (if you're using XA resources like some message queues)
  5. Restart the DTC service (it'll prompt you).

If you're on Windows Firewall (and you should be), make sure port 135 (RPC Endpoint Mapper) and the dynamic DTC ports (default range 49152-65535) are open. MSDTC doesn't use a fixed port by default, so if you're locked down, you'll want to set a fixed port in DTC settings and open that specifically.

I've also seen this fixed by simply restarting the DTC service when a stale config was in memory. Try that first if you're in a hurry, but don't skip the registry check below if it keeps coming back.

Cause #3: Registry flags blocking async promotion

This one's sneaky. Even with everything configured correctly, certain registry keys can prevent MSDTC from promoting a local transaction to a distributed one using the async path. This is more common on older Windows Server versions (2012, 2016) that have had cumulative updates applied in a weird order.

The symptom: Your code is identical to Cause #1's fix, but you still get XACT_E_NOASYNC intermittently, especially under load. Or it works fine on your dev machine but fails on the server.

Check these registry keys

HKLM\SOFTWARE\Microsoft\MSDTC\XACT\EnableAsync
HKLM\SOFTWARE\WOW6432Node\Microsoft\MSDTC\XACT\EnableAsync

If EnableAsync exists and its value is 0, that's your culprit. It disables async support in the transaction manager. Set it to 1 and reboot, or restart the DTC service.

If the key doesn't exist, you can create it (DWORD value) and set it to 1. That's a known fix for some .NET Framework 4.6.2+ environments where async transactions just won't promote.

Also worth checking: HKLM\SOFTWARE\Microsoft\MSDTC\CM\AllowAsyncPromote. Same rule — set it to 1 if it's 0 or missing. These keys control explicitly whether MSDTC allows async promotion, and they're not touched by standard DTC configuration UI.

Now, before you go editing the registry, back it up. I don't want you on the phone with your network admin after you've nuked the DTC config. But honestly, these two keys are safe to set to 1 — they're documented in Microsoft's internal notes, just not public docs.

Quick-reference summary

CauseSymptomFix
Async call without async flowError occurs on first async call inside TransactionScopeUse TransactionScopeAsyncFlowOption.Enabled and target .NET 4.5.1+
MSDTC network misconfigurationError appears only when distributed transaction is attempted over networkEnable Network DTC Access, Inbound/Outbound, open port 135 and DTC ports
Registry disabling asyncIntermittent error, often on server, with correct codeSet EnableAsync and AllowAsyncPromote to 1

That's the whole playbook. If you've gone through all three and still get the error, the next step is to grab a trace with tracelog or WCF tracing, but I've rarely seen it get that far. Fix the async flow first, then check MSDTC settings, then flip that registry key. One of those will get you back to shipping features.

Related Errors in Database Errors
WriteConcernTimeout MongoDB Write Concern Timeout Exceeded – Fix It Fast SQL Query Returns Different Results Each Time You Run It Locked Queries in phpMyAdmin: Quick Fixes SQLITE_IOERR Database corruption: SQLite disk I/O error 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.