0X00001AB7

Fix ERROR_TRANSACTIONS_NOT_FROZEN (0X00001AB7) Fast

Database Errors Intermediate 👁 0 views 📅 Jun 10, 2026

0X00001AB7 means you tried to thaw transactions that weren't frozen. Root cause is mismatched freeze/thaw calls in TPM or SQL scripts. Fix it by checking your freeze state.

Quick answer: You're calling ThawTransaction on a transaction that was never frozen. Check your code for an extra thaw call or a skipped freeze.

Why This Error Happens

I've seen this error pop up in two places: custom TPM (Transactional PowerShell Modules) scripts and SQL Server stored procedures that manage distributed transactions. The error code 0X00001AB7 maps to ERROR_TRANSACTIONS_NOT_FROZEN in the Windows kernel transaction manager. It means your application sent a ThawTransaction request for a transaction handle that's not in a frozen state.

This tripped me up the first time too. The freeze-thaw mechanism works like a countdown lock — you can't skip to step 2 if step 1 hasn't happened. Common triggers include:

  • A script that runs freeze and thaw in different loops, but the freeze loop exits early due to an exception.
  • A bug in a wrapper function that calls thaw twice on the same transaction.
  • Manual intervention where someone ran a thaw command against the wrong transaction ID.

Fix Steps

  1. Identify the offending transaction handle. If you're using PowerShell with TPM, run Get-TpmTransaction | Select-Object -Property Id, State. Look for transactions with State = 'Active' (not 'Frozen').
  2. Review your freeze/thaw call pair. In C++, check this pattern:
    // BAD: Thaw without matching freeze
    BOOL bResult = ThawTransaction(hTransaction); // Fails with 0X00001AB7
    
    // GOOD: Pair freeze and thaw
    BOOL bResult = FreezeTransaction(hTransaction);
    // ... do work ...
    BOOL bResult = ThawTransaction(hTransaction);
    
  3. Check for nested transactions. If you're using System.Transactions.TransactionScope in .NET, nested scopes can create confusion. Only the outermost scope can freeze. Verify you're not calling freeze in a nested scope and thaw in the parent.
  4. Log the transaction state before each call. Add a debug line like DWORD dwState = GetTransactionState(hTransaction); to confirm State == 2 (Frozen) before thawing. On Windows 10/11 and Server 2016+, this API is in ktmw32.dll.

Alternative Fixes

If the main steps don't work:

  • Reboot the machine. Yes, it sounds basic, but I've seen orphaned transaction handles survive process restarts. A full reboot clears the kernel transaction table.
  • Use a tool like Process Monitor to trace the exact API calls. Filter by Process Name = your app and Operation = 'IRP_MJ_CREATE' on \Kernel\Transactions. You'll see every freeze and thaw call in order.
  • If this is in SQL Server, check sys.dm_tran_active_transactions for transactions with transaction_state = 2 (active) vs 4 (frozen). Run DBCC OPENTRAN to find the oldest open transaction — it might be blocking freeze from ever running.

Prevention Tips

  1. Always wrap freeze and thaw in a try-finally block. The thaw must run even if your code throws an exception between freeze and thaw. In C++: __try { FreezeTransaction(h); } __finally { ThawTransaction(h); }
  2. Use a state machine pattern. Keep a boolean flag like bool m_bFrozen that you set to true only after a successful freeze, and check before thaw. This catches double-thaws at compile time rather than runtime.
  3. Add a timeout. Freeze holds resources — if your app crashes after freeze but before thaw, those transactions stay frozen. Use SetTransactionFrozenTimeout (available in Windows 10 1903+) to auto-thaw after 30 seconds.

I know this error is infuriating because it's usually a logic bug, not a system failure. But once you trace the call pair, it's a quick fix. Drop me a comment if your specific scenario isn't covered — I'll help you track it down.

Was this solution helpful?