napi-rs/napi-rs · error · InvalidArg
Invalid number of arguments
Error message
Invalid number of arguments
What it means
Raised in the macro-generated `TupleFromSliceValues` when the number of JS arguments does not exactly match the Rust tuple arity: `values.try_into()` on the slice fails and the library maps it to InvalidArg "Invalid number of arguments". It enforces strict fixed-arity calls for tuple-typed function parameters.
Solutions
- Pass exactly the number of arguments declared in the generated .d.ts signature.
- Use undefined for Option<T> parameters if the signature allows them, instead of omitting positions.
- Regenerate/inspect index.d.ts after changing the Rust function and update all call sites.
- Add a JS-side arity check before invoking the native function.
Example fix
// before mod.add(1); // after mod.add(1, 2);
Defensive patterns
Strategy: validation
Validate before calling
function assertArity(args, n) { if (args.length !== n) throw new Error(`expected ${n} args, got ${args.length}`); }
assertArity([a, b], 2); Try / catch
try { mod.add(a, b); } catch (e) { if (e.message === 'Invalid number of arguments') console.error('check the .d.ts signature'); throw e; } Prevention
- Call native functions with the exact arity from the generated .d.ts.
- Use a thin typed JS wrapper per native function to centralize arity checks.
- Re-run snapshot tests (test -u) after changing Rust signatures to catch call-site drift.
When it happens
Trigger: Calling a native function with too few or too many arguments relative to its declared Rust parameters, e.g. calling `fn add(a: u32, b: u32)` with `add(1)` or `add(1, 2, 3)`. Also when a wrapper/macro passes a slice of args of the wrong length.
Common situations: API signature changed after a rebuild while old JS call sites remain; optional-argument calls against functions without Option parameters; spreading arrays with unexpected length.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Arguments index out of range
- There is no arguments
- Arguments length of #[module_exports] function must be 1 or…
- InvalidArg
- InvalidArg
AI-assisted analysis of napi-rs/napi-rs@39bd1205e4 (2026-09-13).
Data as JSON: /api/errors/4a443310c25c49dc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/napi/src/bindgen_runtime/js_values/function.rs:67
FnArgs { data: value }
}
}
macro_rules! impl_tuple_conversion {
($($ident:ident),*) => {
impl<$($ident: ToNapiValue),*> JsValuesTupleIntoVec for FnArgs<($($ident,)*)> {
#[allow(clippy::not_unsafe_ptr_arg_deref)]
fn into_vec(self, env: sys::napi_env) -> Result<Vec<sys::napi_value>> {
#[allow(non_snake_case)]
let ($($ident,)*) = self.data;
Ok(vec![$(unsafe { <$ident as ToNapiValue>::to_napi_value(env, $ident)? }),*])
}
}
impl<$($ident: FromNapiValue),*> TupleFromSliceValues for ($($ident,)*) {
unsafe fn from_slice_values(env: sys::napi_env, values: &[sys::napi_value]) -> $crate::Result<Self> {
#[allow(non_snake_case)]
let [$($ident),*] = values.try_into().map_err(|_| crate::Error::new(
crate::Status::InvalidArg,
"Invalid number of arguments",
))?;
Ok(($(
unsafe { $ident::from_napi_value(env, $ident)?}
,)*))
}
}
};
}
impl_tuple_conversion!(A);
impl_tuple_conversion!(A, B);
impl_tuple_conversion!(A, B, C);
impl_tuple_conversion!(A, B, C, D);
impl_tuple_conversion!(A, B, C, D, E);
impl_tuple_conversion!(A, B, C, D, E, F);
impl_tuple_conversion!(A, B, C, D, E, F, G);View on GitHub (pinned to 39bd1205e4)