0XC000070C

STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FA (0xC000070C)

Threadpool tried to release a semaphore it doesn't own during I/O completion. Real fix is code or driver-level, not a quick Windows tweak.

Quick answer: 0xC000070C is a kernel-level bugcheck that fires when a threadpool callback releases a semaphore on an I/O completion it doesn't own — you fix it in the driver or app code, not in Windows settings.

What's actually happening here is a mismatch between who acquires the semaphore and who releases it during I/O completion. The Windows threadpool (the one in ntdll, not the .NET one) queues work items to complete IRPs. When your completion routine calls KeReleaseSemaphore or NtReleaseSemaphore on a semaphore that the threadpool associated with a completely different completion, the kernel notices the count would go above the maximum and bugchecks. This shows up most often in third-party filter drivers, antivirus mini-filters, backup agents (Veeam, Acronis), and older VPN clients that hook the network stack. On Windows 10 21H2 and Windows 11 22H2 I've seen it in klif.sys (Kaspersky), atc.sys (older Acronis), and wg.sys before WireGuard 0.5.3. If you're a developer seeing this under Driver Verifier, the verifier's "Threadpool" and "Deadlock detection" options are what caught it. If you're an end user, you've got a bad driver and the fix is removing or updating it.

Why the kernel throws this specific code

The threadpool in Windows (introduced properly in Vista, refined in Windows 7 and again in 10) maintains per-CPU worker threads and a set of synchronization primitives. When you queue a work item with IoQueueWorkItem or use TrySubmitThreadpoolCallback, the pool tracks a reference. If your callback releases a semaphore whose owning thread is not the current worker, or releases it more times than it acquires — the pool's internal accounting goes negative and the kernel bugchecks to prevent silent memory corruption.

The full name tells you everything: STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FA. "On completion" refers to the I/O completion path. "FA" is the fast-fail variant — the kernel chose to crash rather than let the count roll over. That's deliberate. A semaphore count going above max means somebody will eventually wait forever, and deadlocked kernel threads are much worse than a bugcheck.

Step-by-step fix

  1. Get the bugcheck parameters. Open WinDbg (or WinDbg Preview from the Store) and load the minidump from C:\Windows\Minidump. Run !analyze -v. Parameter 1 is usually the semaphore object, parameter 2 the calling thread, parameter 3 the IRP. That IRP tells you which driver is lying.
  2. Identify the offending driver. In the WinDbg output, look at the STACK_TEXT and FAILURE_BUCKET_ID. If it says something like 0xC000070C_nt!KiFastFailDispatch_klif!KliIfReleaseSemaphore, you've found it. Note the exact module name.
  3. Check that driver's version. Right-click the .sys file, Properties, Details tab. Compare against the vendor's current release. Kaspersky fixed this in 21.3.10.391; older builds crash on Windows 11 22H2 after a specific Windows Update. Acronis fixed it in True Image 2021 build 39216.
  4. Remove or update the driver. If it's an AV filter, uninstall via the vendor's removal tool (Kaspersky has kavremover; Bitdefender has bdremover). Don't just disable the service — the filter driver still loads in some cases. For a VPN, uninstall the TAP adapter completely from Device Manager and reboot.
  5. Verify the fix. Reboot and, if you can, run Driver Verifier against the remaining third-party drivers: verifier /standard /driver klif.sys. If the system boots clean for 24 hours of normal use, you're done. Turn Verifier off with verifier /reset when finished — leaving it on permanently slows things down measurably.

If the main fix doesn't work

Sometimes the driver is gone but the crash persists because a leftover filter remains registered. Check with fltmc filters in an admin command prompt. Legacy minifilters stay attached until the altitude registry entries are cleaned. Look under HKLM\SYSTEM\CurrentControlSet\Services\<drivername>\Instances and remove the stale subkeys if the vendor's uninstaller missed them.

If you're a developer and this fires inside your own code, the cause is almost always releasing a semaphore from a completion routine that didn't acquire it. The pattern to look for:

// WRONG — completion routine releases a semaphore acquired elsewhere
NTSTATUS Completion(PDEVICE_OBJECT dev, PIRP irp, PVOID ctx) {
    KeReleaseSemaphore(&g_Semaphore, IO_NO_INCREMENT, 1, FALSE);
    return STATUS_MORE_PROCESSING_REQUIRED;
}

The reason this fails is the threadpool doesn't track the semaphore as belonging to that callback. Acquire it in the same routine, or use a KEVENT set with KeSetEvent and let the waiter handle its own state. Releasing from a different thread than the acquirer is legal for semaphores but only when the counts balance — if the pool's worker gets recycled mid-flight, the accounting breaks.

Also check that you're not double-releasing on error paths. A completion routine that returns STATUS_MORE_PROCESSING_REQUIRED and then queues another work item that also releases is a classic double-release. Use a single owner and a boolean flag.

Prevention

For end users: don't stack multiple AV products, and don't install a VPN client that ships its own NDIS filter on top of a Kaspersky/Bitdefender install. That combination is where I've seen this bugcheck most in the wild. Keep filter drivers current — vendors patch these fast once Windows changes the pool internals, and the 22H2 update did change them.

For developers: acquire and release within the same callback, never across the completion boundary. If you need cross-thread signaling, use an event, not a semaphore. And run with Driver Verifier's threadpool and handle-tracking options enabled during development. Catching this in the lab beats a customer's blue screen at 3am.

Related Errors in Windows Errors
0X80000011 STATUS_DEVICE_BUSY (0x80000011): The Device Is Currently Busy 0X000019E8 Fix ERROR_LOG_ARCHIVE_NOT_IN_PROGRESS 0X000019E8 0XC00B0002 STATUS_MUI_INVALID_FILE (0xC00B0002) – Corrupt MUI File Fix 0X80004032 CO_E_SXS_CONFIG (0X80004032) Fix: Invalid Side-by-Side Config

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.