napi-rs/napi-rs · info · Error

format!($($msg)*)

Error message

format!($($msg)*)

What it means

The `error!` macro expands to `Error::new($status, format!($($msg)*))`, constructing a library error with a formatted message and a caller-chosen `Status`. Any error you see created via `error!(...)` in napi-rs or user code takes its message from the format arguments here.

Solutions

  1. Locate the `error!` call producing your exact message to find the failing validation
  2. Fix the input/condition described by the formatted message
  3. Choose a more specific `Status` than GenericFailure where applicable

Example fix

// before
return Err(error!(Status::GenericFailure, "bad input"));
// after
return Err(error!(Status::InvalidArg, "expected number, got {}", ty));
Defensive patterns

Strategy: try-catch

Try / catch

try { nativeFn(args); } catch (e) {
  if (e.code === 'GenericFailure' || e.code === 'InvalidArg') { /* message came from error! formatting; handle per validation */ }
  else throw e;
}

Prevention

When it happens

Trigger: Any use of `napi::error!(status, "...")` in `#[napi]` code — e.g. `error!(Status::InvalidArg, "expected {} elements", n)` — including inside the crate's own code paths.

Common situations: Custom validation in native functions that returns formatted errors; users searching JS stack traces for these messages should look for the matching `error!` invocation in Rust.

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


AI-assisted analysis of napi-rs/napi-rs@39bd1205e4 (2026-09-13). Data as JSON: /api/errors/9daf5f2c21b2dcbc. Report an issue: GitHub.

Appendix: source

Thrown at crates/napi/src/error.rs:1721

        // value came back as a plain `Error` (its fallback is
        // `JsError::into_value`).
        Ok(unsafe { val.into_value(env) })
      }
    }
  };
}

impl_object_methods!(JsError, sys::napi_create_error);
impl_object_methods!(JsTypeError, sys::napi_create_type_error);
impl_object_methods!(JsRangeError, sys::napi_create_range_error);
#[cfg(feature = "napi9")]
impl_object_methods!(JsSyntaxError, sys::node_api_create_syntax_error);

#[doc(hidden)]
#[macro_export]
macro_rules! error {
  ($status:expr, $($msg:tt)*) => {
    $crate::Error::new($status, format!($($msg)*))
  };
}

#[doc(hidden)]
#[macro_export]
macro_rules! check_status {
  ($code:expr) => {{
    let c = $code;
    match c {
      $crate::sys::Status::napi_ok => Ok(()),
      _ => Err($crate::Error::new($crate::Status::from(c), "".to_owned())),
    }
  }};

  ($code:expr, $($msg:tt)*) => {{
    let c = $code;
    match c {
      $crate::sys::Status::napi_ok => Ok(()),

View on GitHub (pinned to 39bd1205e4)