RPC_E_NO_SYNC (0x80010120): No synchronize objects to wait on
COM call fails because there's no sync object available. Happens when a thread tries to wait on a call but the apartment state doesn't allow it.
Quick answer
Set the COM caller's apartment to MTA (multithreaded apartment) or use CoWaitForMultipleHandles with proper flags. The error means your thread tried to wait on a COM call but didn't have a synchronization object available.
What this error really means
You're seeing 0x80010120 — RPC_E_NO_SYNC — when a COM object call can't complete because the calling thread has no waitable sync object. This usually happens in STA (single-threaded apartment) threads that block waiting for a COM call to return, but the STA's message pump isn't running or can't handle the request.
The real trigger: A Windows service or application makes a COM call to a remote server (or even local out-of-process COM). The call needs to wait for a response, but COM can't set up a proper wait because the calling thread's apartment doesn't allow it. I've seen this most often on Windows Server 2016/2019 when a scheduled task or service tries to call WMI or a COM+ component and the thread is in a broken STA state.
What's actually happening here: COM uses synchronization objects like events or semaphores internally to wait for a call to complete. When it can't create or access one — because the apartment model forbids waiting, or the message loop is dead — it returns this specific error. It's not a network timeout; it's a threading infrastructure failure.
Fix steps
- Check the calling thread's apartment state
Run this in your code to see what apartment the thread is in:
If it's STA, that's your problem. STA threads need a message pump to process COM calls.HRESULT hr = CoGetApartmentType(&aptType, &aptQualifier);
if (aptType == APTTYPE_STA) { /* single-threaded apartment */ }
else if (aptType == APTTYPE_MTA) { /* multithreaded apartment */ } - Switch to MTA if possible
Initialize the thread withCoInitializeEx(NULL, COINIT_MULTITHREADED)instead ofCOINIT_APARTMENTTHREADED. This tells COM the thread can handle multiple calls without waiting on a pump. - If you must stay in STA, run the message pump
In a STA thread, you need to pump messages. Add a loop like:
Call this before and after your COM call. Without this, COM can't dispatch the call's completion.MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} - Use CoWaitForMultipleHandles
Instead of blocking onWaitForSingleObjectorSleep, use COM's own wait function:
This handles the synchronization correctly in both STA and MTA.CoWaitForMultipleHandles(COWAIT_DEFAULT, INFINITE, 1, &hEvent, &index);
Alternative fixes if the main one fails
- If you can't change the apartment model: Run the COM call on a separate MTA thread. Create a worker thread, initialize it as MTA, make the call there, and signal back to the original thread.
- If the error comes from a Windows service: Check the service's SCM configuration. Some services run in a session isolation mode that breaks COM. Set the service to interact with the desktop or run under
LocalSystemaccount. - If it's a third-party component: The component might require a specific apartment. Contact the vendor. I've seen this with old COM+ components that expect a STA but the host process is MTA.
Prevention tip
Always initialize COM explicitly on every thread that makes COM calls. Don't rely on the default apartment. Use CoInitializeEx with the right flag — COINIT_APARTMENTTHREADED for UI threads that need a pump, COINIT_MULTITHREADED for background workers. Test on Windows Server 2022 and Windows 11 because newer OS versions are stricter about apartment compliance.
Also, never block an STA thread with WaitForSingleObject or Sleep while waiting for a COM call. That starves the message pump and triggers exactly this error. Use CoWaitForMultipleHandles or MsgWaitForMultipleObjects instead.
Was this solution helpful?