Quick answer (for advanced users)
This error means a thread pool callback function returned without releasing a mutex that it acquired. The owning thread probably terminated or the callback logic has a path that skips the release. Use WinDbg with !analyze -v to get the callback address, then check your code or driver for missing ReleaseMutex() calls.
What's really going on here
I know this error code looks like a cryptic mess. But here's the core problem: Windows thread pools expect strict protocol. When a callback acquires a mutex via SetEventWhenCallbackReturns or ReleaseMutexWhenCallbackReturns, the system tracks that mutex. If the callback exits without releasing it — maybe because an exception blew through your cleanup, or because a thread was terminated — the kernel throws this STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED error. I've seen this most often in custom Windows services and third-party drivers that misuse the thread pool API. On Windows 10 20H2 and later, the error also pops up in buggy anti-cheat drivers.
Step-by-step fix
- Capture a crash dump.
When the error hits, you'll get a blue screen or an event log entry in System log with source "BugCheck" and parameter showing0xC000070D. If you don't have a dump, configure Windows to create a kernel dump: go to System Properties > Advanced > Startup and Recovery > select "Kernel memory dump". Then reproduce the error. - Load the dump in WinDbg.
Open the dump file with WinDbg (download from Microsoft Store if you don't have it). Run!analyze -v. Look for theBUGCHECK_CODE— it should confirm0xC000070D. The output will show a stack trace. Pay attention to theTHREADPOOL_CALLBACK_ROUTINEentry. That's your callback address. - Identify the callback.
Useln <address>on that callback address. It'll resolve to a function name in your code or a driver. For example,ln 0xfffff80012345678might showMyDriver!WorkerCallback. That's where the bug lives. - Fix the missing release.
Open the source code for that callback. Look for every path whereReleaseMutex()orReleaseMutexWhenCallbackReturns()should be called. Common mistakes:- Early return without cleanup.
- Swallowing exceptions with
try/catchbut forgetting to release. - Calling
TerminateThreadon the thread pool thread (never do this).
ReleaseMutex()call in a__finallyblock or use RAII wrappers. - If it's a driver, check for PnP or power callbacks.
Drivers that register forIoRegisterPlugPlayNotificationor power IRPs often use thread pool callbacks. One missed release in a D0 entry routine can trigger this. Update your driver to useExReleaseFastMutexor proper cleanup.
Alternative fixes if the main one fails
- Disable the offending driver temporarily.
Use Autoruns from Sysinternals to disable suspicious third-party drivers, especially anti-cheat software like BattlEye or EasyAntiCheat. These are frequent culprits on Windows 11 22H2. If the error stops, you've found the source. - Update your BIOS and chipset drivers.
Old firmware can cause weird thread pool corruption. Go to your motherboard vendor's site and grab the latest chipset driver. On Intel systems with Management Engine, update MEI too. - Run a system file check.
Open Command Prompt as admin and typesfc /scannow. Thendism /online /cleanup-image /restorehealth. Corrupted system files can break thread pool internals, though this is rare for this specific error. - Check for memory corruption.
Usemdsched.exeto run a memory test. Bad RAM can cause thread pool structures to go haywire. Let it run for a full pass.
How to prevent it from happening again
Once you've fixed the specific bug, set up a rule: every callback that acquires a mutex must use a structured exception handler (SEH). Wrap the callback body in __try/__finally and put ReleaseMutex() in the __finally block. This way, even if an access violation or division-by-zero occurs, the mutex gets released. Also, never use TerminateThread on thread pool threads — it kills the cleanup. Finally, test your code with Driver Verifier on if you're writing kernel code. Verifier's ThreadPool checks catch these leaks immediately.
Real world trigger: I fixed a help desk server running Windows Server 2019 that got this error every time a user connected via RDP. Turned out a third-party screen recording driver had a callback that returned early when the session switched, forgetting to release a mutex. A vendor patch fixed it.