Quick answer
DBG_EXCEPTION_HANDLED (0x00010001) isn't an error — it's a debug event your process emitted after Windows delivered a first-chance exception to a debugger that said "I handled this." The thread resumes and execution continues.
What's actually happening here
When a debugger attaches to a process with DebugActiveProcess, the kernel routes exceptions through the debugging subsystem before the process's own vectored exception handlers run. The sequence goes like this: the CPU faults, the OS builds an EXCEPTION_RECORD, and the debugger's WaitForDebugEvent gets an EXCEPTION_DEBUG_EVENT. The debugger then calls ContinueDebugEvent with either DBG_EXCEPTION_NOT_HANDLED (0x80010001) or DBG_EXCEPTION_HANDLED (0x00010001).
The reason step 3 works is that DBG_EXCEPTION_HANDLED tells the kernel to treat the exception as resolved — no second-chance dispatch, no unhandled exception filter, no WER dialog. The process keeps running. You'll typically see this in three places: WinDbg's event log, a custom debugger loop that logs every DEBUG_EVENT, or Windows Event Viewer when a tool like Application Verifier or a JIT debugger is attached.
Common real-world trigger: a .NET app throws a FileNotFoundException during config probing. Visual Studio catches it as a first-chance exception, the developer hits Continue, and VS resumes with DBG_EXCEPTION_HANDLED. The app never crashed. Someone later greps the trace and mistakes the code for a failure.
Fix steps
- Confirm you're looking at a debug event, not a fault. Check the surrounding log lines. If you see a matching
EXCEPTION_DEBUG_EVENTimmediately before it, this is expected behavior. If0x00010001appears alone with no prior exception, your logging is incomplete. - Identify who's attached. Run
tasklist /m dbghelp.dllor check forvsjitdebugger.exe,windbg.exe,cdb.exe, orprocdump.exe. Any of these can produce the event. If your production service prints this code, something is attached that shouldn't be. - Stop logging it as an error. In your
WaitForDebugEventloop, treat0x00010001as informational. Filter it:
The first-chance flag inif (debugEvent.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) { /* ... */ } else if (debugEvent.u.Exception.dwFirstChance) { /* first chance */ } else { /* second chance — this one matters */ }EXCEPTION_DEBUG_INFOis the field you care about, not the continue status. - If you don't want the debugger to swallow exceptions, change its policy. In Visual Studio: Debug > Windows > Exception Settings, uncheck the exception types you want to break on. In WinDbg, set
sxefor specific exceptions orsxdto disable breaks. The debugger's continue status is a symptom of its configuration, not a bug in your code. - For kernel-mode debugging, check
DEBUG_STATUS. Driver devs sometimes see0x00010001inDbgPrintoutput afterKdBreakPoint. The same rule applies: it means the exception was handled. Verify with!analyze -vbefore assuming anything broke.
Alternative fixes
- Disable just-in-time debugging. If a stray JIT debugger attaches to a released build, remove
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug(or the WOW6432Node equivalent) and clear theDebuggervalue. Reboot or restart the process. - Kill the debugger host. If
vsjitdebugger.exeis orphaned,taskkill /f /im vsjitdebugger.exe. It's a common leftover after a crashed debug session. - Use
SetUnhandledExceptionFiltercarefully. If you're writing your own handler, don't confuse it with the debug event path. A debugger attached overrides your filter entirely until you detach. - Switch to ETW for tracing. If logging debug events is causing noise, move to
Event Tracing for Windows— it doesn't intercept exceptions the way a debugger does.
Prevention
The real fix is to stop treating debug continue-status codes as errors. 0x00010001 is the debugger saying "I got it." If your monitoring stack fires an alert on it, fix the alert rule. Audit your debugger exception lists — every unchecked exception in Exception Settings is a future false positive. And keep an eye on second-chance exceptions (the ones with dwFirstChance == FALSE), because those are the ones that actually terminate the process. That distinction is the whole game.