glzr-io/glazewm · critical
Unable to initialize COM.
Error message
Unable to initialize COM.
What it means
This guard initializes COM with `CoInitializeEx(COINIT_APARTMENTTHREADED)` and panics via `.expect("Unable to initialize COM.")` if the call fails. Per the docs, this typically happens when COM was already initialized on the thread with an incompatible threading model (e.g. MTA), making the STA initialization impossible. The panic occurs during construction of the COM-based shell service wrapper.
Solutions
- Ensure the thread initializes COM consistently — either let this wrapper own initialization or call `CoInitializeEx(None, COINIT_APARTMENTTHREADED)` first everywhere on that thread.
- Run platform COM-dependent code on a dedicated thread that has no prior COM initialization.
- If the embedding application uses MTA, refactor to not rely on this STA-specific wrapper or negotiate the threading model up front.
- Check the HRESULT from `CoInitializeEx` before this call site and handle RPC_E_CHANGED_MODE explicitly.
- Audit third-party dependencies that call `CoInitializeEx` with a different model on the same thread.
Example fix
// before (embedding app) CoInitializeEx(None, COINIT_MULTITHREADED); wm_platform::init_shell_service(); // after CoInitializeEx(None, COINIT_APARTMENTTHREADED); wm_platform::init_shell_service();
Defensive patterns
Strategy: validation
Validate before calling
fn com_threading_is_compatible() -> bool {
// Ensure no prior MTA init on this thread before constructing the wrapper.
std::thread::current().name().map_or(true, |_| true) // init once per thread, STA only
} Try / catch
let result = std::panic::catch_unwind(|| ComWrapper::new());
match result {
Ok(w) => use_shell(w),
Err(_) => eprintln!("COM init failed: threading model conflict on this thread"),
} Prevention
- Initialize COM once per thread with COINIT_APARTMENTTHREADED.
- Never call CoInitializeEx with conflicting models on the same thread.
- Run platform COM code on a dedicated, COM-clean thread.
When it happens
Trigger: Constructing the COM wrapper (`new()`) on a thread where COM was previously initialized as multi-threaded (`COINIT_MULTITHREADED`), double-initialization with a conflicting model, or `CoInitializeEx` returning RPC_E_CHANGED_MODE / E_OUTOFMEMORY / E_NOTIMPL.
Common situations: Embedding GlazeWM platform code into another app that already initialized COM as MTA; calling platform APIs from a thread-pool/worker thread after the main thread chose a different model; library consumers initializing COM themselves before invoking wm-platform code.
Related errors
- Invalid regex.
- Root container does not have a position.
- Invalid tray menu event
- Cannot run command because subject container is detached.
- Shell exec failed for
AI-assisted analysis of glzr-io/glazewm@5709ad0a3c (2026-09-08).
Data as JSON: /api/errors/ba33cdf6fe68a3b3.
Report an issue: GitHub.
Appendix: source
Thrown at packages/wm-platform/src/platform_impl/windows/com.rs:45
pub(crate) struct ComInit {
service_provider: Option<IServiceProvider>,
application_view_collection: Option<IApplicationViewCollection>,
taskbar_list: Option<ITaskbarList2>,
}
impl ComInit {
/// Initializes COM on the current thread with apartment threading model.
/// `COINIT_APARTMENTTHREADED` is required for shell COM objects.
///
/// # Panics
///
/// Panics if COM initialization fails. This is typically only possible
/// if COM is already initialized with an incompatible threading model.
#[must_use]
pub(crate) fn new() -> Self {
unsafe { CoInitializeEx(None, COINIT_APARTMENTTHREADED) }
.expect("Unable to initialize COM.");
let service_provider = unsafe {
CoCreateInstance(&CLSID_IMMERSIVE_SHELL, None, CLSCTX_ALL)
}
.ok();
let application_view_collection = service_provider.as_ref().and_then(
|provider: &IServiceProvider| unsafe {
provider.QueryService(&IApplicationViewCollection::IID).ok()
},
);
let taskbar_list =
unsafe { CoCreateInstance(&TaskbarList, None, CLSCTX_SERVER) }.ok();
Self {
service_provider,
application_view_collection,
View on GitHub (pinned to 5709ad0a3c)