{"record":{"id":"4a443310c25c49dc","repo":"napi-rs/napi-rs","slug":"invalid-number-of-arguments","errorCode":null,"errorMessage":"Invalid number of arguments","messagePattern":"Invalid number of arguments","errorType":"validation","errorClass":"InvalidArg","httpStatus":null,"severity":"error","filePath":"crates/napi/src/bindgen_runtime/js_values/function.rs","lineNumber":67,"sourceCode":"    FnArgs { data: value }\n  }\n}\n\nmacro_rules! impl_tuple_conversion {\n  ($($ident:ident),*) => {\n    impl<$($ident: ToNapiValue),*> JsValuesTupleIntoVec for FnArgs<($($ident,)*)> {\n      #[allow(clippy::not_unsafe_ptr_arg_deref)]\n      fn into_vec(self, env: sys::napi_env) -> Result<Vec<sys::napi_value>> {\n        #[allow(non_snake_case)]\n        let ($($ident,)*) = self.data;\n        Ok(vec![$(unsafe { <$ident as ToNapiValue>::to_napi_value(env, $ident)? }),*])\n      }\n    }\n\n    impl<$($ident: FromNapiValue),*> TupleFromSliceValues for ($($ident,)*) {\n      unsafe fn from_slice_values(env: sys::napi_env, values: &[sys::napi_value]) -> $crate::Result<Self> {\n        #[allow(non_snake_case)]\n        let [$($ident),*] = values.try_into().map_err(|_| crate::Error::new(\n          crate::Status::InvalidArg,\n          \"Invalid number of arguments\",\n        ))?;\n        Ok(($(\n          unsafe { $ident::from_napi_value(env, $ident)?}\n        ,)*))\n      }\n    }\n  };\n}\n\nimpl_tuple_conversion!(A);\nimpl_tuple_conversion!(A, B);\nimpl_tuple_conversion!(A, B, C);\nimpl_tuple_conversion!(A, B, C, D);\nimpl_tuple_conversion!(A, B, C, D, E);\nimpl_tuple_conversion!(A, B, C, D, E, F);\nimpl_tuple_conversion!(A, B, C, D, E, F, G);","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/napi-rs/napi-rs/blob/39bd1205e480a453a2da2601a760bde5a71ed016/crates/napi/src/bindgen_runtime/js_values/function.rs#L49-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmod.add(1);\n// after\nmod.add(1, 2);","handlingStrategy":"validation","validationCode":"function assertArity(args, n) { if (args.length !== n) throw new Error(`expected ${n} args, got ${args.length}`); }\nassertArity([a, b], 2);","typeGuard":null,"tryCatchPattern":"try { mod.add(a, b); } catch (e) { if (e.message === 'Invalid number of arguments') console.error('check the .d.ts signature'); throw e; }","preventionTips":["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."],"tags":["arguments","arity","napi","signature"],"backgroundTag":"missing-required-argument","analyzedSha":"39bd1205e480a453a2da2601a760bde5a71ed016","analyzedAt":"2026-09-13T20:31:47.814Z","contentChangedAt":"2026-09-13T20:31:47.814Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}