denoland/deno · critical
Initialize libloading failed {}
Error message
Initialize libloading failed {} What it means
On Windows, the napi_sys bindings resolve N-API function pointers from the host module at runtime. setup() must run once before any binding is used: it obtains the current module handle via libloading::os::windows::Library::this() and panics if the handle cannot be acquired, because no napi function pointer could be resolved afterwards.
Source
Thrown at libs/napi_sys/src/lib.rs:125
pub use types::*;
#[cfg(windows)]
static SETUP: Once = Once::new();
/// Loads N-API symbols from host process.
/// Must be called at least once before using any functions in bindings or
/// they will panic.
///
/// # Safety
///
/// `env` must be a valid `napi_env` for the current thread.
#[cfg(windows)]
pub unsafe fn setup() {
SETUP.call_once(|| {
let host = match libloading::os::windows::Library::this() {
Ok(lib) => lib.into(),
Err(err) => {
panic!("Initialize libloading failed {}", err);
}
};
// SAFETY: Once ensures single-threaded init; host is a valid library handle.
unsafe {
if let Err(err) = functions::load(&host) {
panic!("{}", err);
}
}
});
}
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Compile and load the napi glue as a real DLL on Windows so the current module handle exists
- Call napi_sys::setup() exactly once during module/thread initialization before touching any binding
- If you control the host, load the library with LoadLibrary instead of static linking so libloading can find the handle
- Wrap setup in std::panic::catch_unwind during bring-up to convert the abort into a reportable startup error
Example fix
// before
unsafe { napi_sys::setup(); } // panics: Initialize libloading failed ...
// after
let ok = std::panic::catch_unwind(|| unsafe { napi_sys::setup() });
if ok.is_err() {
return Err("napi_sys setup failed: host module handle unavailable");
} Defensive patterns
Strategy: validation
Validate before calling
// Windows-only pre-check mirroring what setup() needs to succeed
#[cfg(windows)]
fn can_resolve_host_module() -> bool {
libloading::os::windows::Library::this().is_ok()
}
// run before any napi work
if cfg!(windows) && !can_resolve_host_module() {
return Err("napi unavailable: host module handle cannot be resolved");
} Try / catch
let setup = std::panic::catch_unwind(|| unsafe { napi_sys::setup() });
if setup.is_err() {
// report a startup error instead of aborting the host process
} Prevention
- Always run napi_sys::setup() during deterministic initialization, before any binding can be reached
- Load the napi glue as a DLL on Windows; never statically link it into an executable
- Add a startup smoke test that calls setup() so packaging regressions surface immediately
When it happens
Trigger: Calling unsafe napi_sys::setup() on Windows in a host where Library::this() fails to return the current DLL handle: the napi glue is statically linked into an executable, loaded through a custom loader that does not register a module handle, or the HMODULE context is otherwise unavailable.
Common situations: Embedding Deno's napi compatibility layer into a non-Deno host on Windows; test harnesses that load the module in unusual ways; packaging changes (static vs dynamic linking) that leave the module without a resolvable handle.
Related errors
- Unable to deserialize result parameter.
- {}: ({}) {}
- failed to unregister: {}
- Cannot access pointer: expected 'ArrayBuffer', 'SharedArrayB
- Cannot get pointer size: found recursive struct
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/667df12187f81b73.
Report an issue: GitHub.