neon-bindings/neon · error

Failed to find N-API version

Error message

Failed to find N-API version

What it means

During symbol loading, `napi_get_version` was resolved from the host library via libloading, but the call either failed to load the symbol or did not return Status::Ok, so the Node-API version reported by the running Node process could not be determined. This indicates the module is not running inside a Node-API-capable host (e.g. loaded by a non-Node process) or a broken libloading resolution.

Solutions

  1. Run the module under a Node.js version that supports Node-API (napi_get_version is available since Node 10+ / all N-API-capable releases)
  2. Do not load the .node addon via dlopen/LoadLibrary from non-Node host processes
  3. On Windows, ensure the module is loaded through the normal require() path so Library::this() resolves the host correctly
  4. Check `Error: Module did not self-register` cases — the module may have been linked against a host without N-API

Example fix

Load the addon with a supported Node.js runtime (Node >= the version matching the crate's napi feature); do not dlopen the .node addon from non-Node processes.
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: `load` runs when the native module is registered; it panics if `get_version` cannot resolve `napi_get_version` from the host process or the call returns a status other than Status::Ok — i.e. the host has no Node-API support.

Common situations: Native module loaded outside of Node.js (e.g. from another FFI host); a Node binary so old it lacks N-API; corrupted/incompatible libloading setup on Windows where `Library::this()` itself fails.


AI-assisted analysis of neon-bindings/neon@38960e4381 (2026-09-13). Data as JSON: /api/errors/49b3eda20a51175c. Report an issue: GitHub.

Appendix: source

Thrown at crates/neon/src/sys/bindings/functions.rs:458

// This symbol is loaded separately because it is a prerequisite
unsafe fn get_version(host: &libloading::Library, env: Env) -> Result<u32, libloading::Error> {
    let get_version = host.get::<fn(Env, *mut u32) -> Status>(b"napi_get_version")?;
    let mut version = 0;

    assert_eq!(get_version(env, &mut version as *mut _), Status::Ok,);

    Ok(version)
}

pub(crate) unsafe fn load(env: Env) -> Result<(), libloading::Error> {
    #[cfg(not(windows))]
    let host = libloading::os::unix::Library::this().into();
    #[cfg(windows)]
    let host = libloading::os::windows::Library::this()?.into();

    // This never fail since `get_version` is in N-API Version 1 and the module will fail
    // with `Error: Module did not self-register` if N-API does not exist.
    let actual_version = get_version(&host, env).expect("Failed to find N-API version");

    let expected_version = match () {
        _ if cfg!(feature = "napi-8") => 8,
        _ if cfg!(feature = "napi-7") => 7,
        _ if cfg!(feature = "napi-6") => 6,
        _ if cfg!(feature = "napi-5") => 5,
        _ if cfg!(feature = "napi-4") => 4,
        _ if cfg!(feature = "napi-3") => 3,
        _ if cfg!(feature = "napi-2") => 2,
        _ => 1,
    };

View on GitHub (pinned to 38960e4381)