0X40190035

STATUS_RM_ALREADY_STARTED (0X40190035) – What It Means and How to Fix It

Database Errors Intermediate 👁 12 views 📅 May 28, 2026

This error means a transactional resource manager (RM) tried to start twice. Usually a driver or service issue. Restarting the dependent services fixes it.

Quick answer: Restart the KtmRm and MSDTC services via net stop KtmRm && net start KtmRm (run as admin), then retry your transaction-based operation.

What's Actually Happening Here

The error code 0X40190035STATUS_RM_ALREADY_STARTED — is thrown by the Windows Kernel Transaction Manager (KTM) when a transactional resource manager (RM) tries to Start more than once without a proper Stop in between. In practice, you'll see this when using fsutil transaction commands, or when SQL Server, MSDTC, or a custom transactional application tries to open a transaction and the underlying RM is already in a 'started' state from a previous call that didn't clean up.

The typical trigger: you're working on a Windows Server 2019 or 2022 box, you run a PowerShell script that uses TransactionScope with DTC, the script crashes mid-transaction, and the next run barfs with this exact hex error. The RM — think of it as a lightweight kernel-mode coordinator that tracks open transactions — is still flagged as active. Windows is conservative here: it won't silently restart it because that could orphan pending operations. So it says no.

Fix Steps

  1. Open an elevated command prompt. Hit Win+X, select Terminal (Admin). You need admin rights to talk to the KTM service.
  2. Check the RM's current state. Run:
    fsutil transaction list

    You'll probably see one or more transactions with a Status of 'Active' and a Resource Manager ID listed. Note the RM ID.
  3. Restart the Kernel Transaction Manager service. This kills all stale RM instances cleanly:
    net stop KtmRm && net start KtmRm

    If the service won't stop because a dependency (like MSDTC) refuses, stop that first:
    net stop MSDTC

    Then restart KtmRm, then restart MSDTC:
    net start KtmRm && net start MSDTC
  4. Verify the RM is gone. Run fsutil transaction list again. The list should be empty. If it's not empty, you have a persistent transaction that won't release — see the next section.
  5. Retry your operation. Run your application or script again. The error should vanish.

If That Doesn't Work: Forced Cleanup via PowerShell

Sometimes the RM has a PID attached that's actually a dead process. Windows won't release it because it thinks the process is still alive. You can nuke it directly:

Get-WmiObject -Class Win32_Transaction -Filter "ResourceManagerID = '{YOUR_RM_ID}'" | Remove-WmiObject

Replace YOUR_RM_ID with the GUID you saw in step 2. This bypasses the normal stop sequence and yeets the transaction object. Only do this when you're certain no real application is using that RM. A reboot also works, but it's slower.

Prevention Tip

The root cause is almost always an application that crashes or gets killed without finishing its transaction. If your code uses TransactionScope, wrap it in a try/finally that calls Complete() only on success and Dispose() on the finally block. Don't rely on garbage collection — the RM stays open until the transaction object is explicitly disposed. If you're writing a long-running script, always call Rollback() on errors.

But the real prevention on the OS level: set the KtmRm service to Manual and only start it when needed. That way a dirty RM state is less likely to survive across reboots. On servers that do heavy transactional work (SQL Server, BizTalk), I've seen admins schedule a nightly net stop KtmRm and net start KtmRm as a cleanup job. It's brute-force, but it works.

Alternative Fix: Registry Tweak (Advanced)

If you're on a dev machine and you keep hitting this because your code is buggy, you can tell Windows to automatically reset the RM after a crash. Add this DWORD:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\KtmRm\EnableAutoReset
Value: 1

Then reboot. This makes KTM treat a crashed RM as automatically cleaned up. Don't do this on production. It can mask real transaction failures and leave partial writes visible to other transactions. The error exists for a reason — it's warning you something didn't finish properly.

Was this solution helpful?