| Previous | Next |
| ERROR_ABANDONED_WAIT_63 | ERROR_KERNEL_APC |
ERROR_USER_APC
User APC affected an alertable wait
ERROR_USER_APC is Windows system result 737 (0x000002E1). This value is an internal or translated APC-related marker rather than an ordinary signaled-object index.
This result points to user-mode asynchronous procedure call delivery on an alertable thread. Public alertable wait functions commonly report WAIT_IO_COMPLETION, so code 737 must be tied to the layer that performed the translation.
Where this value belongs
- Thread enters an alertable wait and a queued user APC executes.
- Completion routine is delivered on the initiating thread.
- Native or compatibility layer records APC delivery as it.
User APC execution does not prove that the object originally awaited is signaled. The callback can change application state, queue more work, or request cancellation, so the wait predicate must be evaluated again.
Common interpretation mistakes
- It is mishandled when APC delivery is treated as completion of the protected operation.
- It is mishandled when the callback performs a blocking alertable wait and causes recursive APC dispatch.
- It is mishandled when the target thread exits before queued APC work can run.
- It is mishandled when a wrapper hides whether the original API returned WAIT_IO_COMPLETION or another status.
Diagnostic sequence
- Identify the alertable wait API and its alertable flag.
- Record the thread that queued the APC and the target thread.
- Capture the APC routine identity and queue timestamp.
- Check callback reentrancy and whether it modified the wait predicate.
- After callback return, test cancellation and object state again.
- Bound repeated APC wakeups so the thread cannot starve its primary work.
Evidence worth keeping
- preserve queueing and target thread IDs.
- preserve APC routine or completion callback identity.
- preserve alertable wait function and timeout.
- preserve callback start/end timestamps and nesting depth.
- preserve predicate state before and after APC execution.
A trace should link the queue operation to the eventual callback; merely recording that the wait woke up cannot show whether useful APC work ran.
Correct handling and recovery
Allow the user APC callback to complete under its documented restrictions, then loop back through cancellation and object-state checks. Do not dispatch an arbitrary wait-array index.
Reissuing the alertable wait is expected when the primary predicate remains false. Reissuing the operation represented by the callback requires its own completion and idempotency rules.
Difference from nearby values
ERROR_KERNEL_APC concerns kernel APC processing and does not mean a user callback ran. ERROR_ALERTED represents an alerted return without the same user-APC callback semantics.
Practical scenario
An overlapped I/O completion routine runs while a worker waits alertably for shutdown. The wrapper logs it, the worker processes the completion, then checks shutdown again instead of assuming the shutdown event fired.
Implementation guidance
Keep APC callbacks short, nonblocking, and reentrancy-aware. Prefer explicit completion queues when complex work or cross-thread ownership is required.
Record user_apc_queuer, user_apc_target, user_apc_routine, user_apc_nesting, and user_apc_predicate_after.
References
- Microsoft: System Error Codes 500–999
- Microsoft: Asynchronous procedure calls
- Microsoft: QueueUserAPC
- Microsoft: WaitForSingleObjectEx
Looking for a different code? Search another status or error code.
