napi-rs/napi-rs · error
InvalidArg
InvalidArg
Error message
referenced ptr is null
What it means
This is a codegen-injected guard: when generated #[napi] function argument conversion needs to take a reference to an argument (make_ref), it checks the raw pointer for null and throws InvalidArg 'referenced ptr is null' if it is null. Hitting it means a required reference argument arrived as a null raw pointer, which the generated code refuses to reference.
Solutions
- Pass a real, non-null value for the argument instead of null/undefined
- Check the generated .d.ts signature and supply all required reference arguments
- If the argument is optional in your design, change the Rust signature to Option<T> so null is handled
- Regenerate bindings if the addon was rebuilt with a different signature
Example fix
// before
mod.doWork(null) // ptr is null -> InvalidArg
// after
mod.doWork({ id: 1 }) Defensive patterns
Strategy: validation
Validate before calling
function requireRef(v, name) { if (v === null || v === undefined) throw new TypeError(name + ' must be a non-null object'); return v } Type guard
const isNonNullObject = (v) => v !== null && (typeof v === 'object' || typeof v === 'function')
Try / catch
try {
addon.fn(arg)
} catch (e) {
if (e.code === 'InvalidArg' && /referenced ptr is null/.test(e.message)) {
throw new TypeError('arg must not be null/undefined')
}
throw e
} Prevention
- Never pass null/undefined where the generated .d.ts shows a required reference type
- Model optional native arguments as Option<T> in Rust so null is legal
- Regenerate and review .d.ts signatures after changing Rust function signatures
When it happens
Trigger: Calling a generated napi function whose argument conversion uses make_ref with a null/undefined or otherwise null-backed value where a non-null reference is required (e.g. passing null for an argument typed as an object/class reference in a generated binding).
Common situations: Calling a native addon function with null/undefined for an argument expected to be a real object; FFI-level misuse where a pointer field was never populated; mismatches between generated bindings and the JS values passed.
Related errors
- InvalidArg
- InvalidArg
- Borrowed data should not be null
- Object is not array
- Invalid argument, nothing attach to js_object
AI-assisted analysis of napi-rs/napi-rs@39bd1205e4 (2026-09-13).
Data as JSON: /api/errors/889493ff38340c55.
Report an issue: GitHub.
Appendix: source
Thrown at crates/backend/src/codegen/fn.rs:1080
}
}
}
}
Type::Reference(TypeReference {
lifetime: Some(lt), ..
}) => {
*lt = syn::Lifetime::new("'_", Span::call_site());
}
_ => {}
}
Ok(())
}
fn make_ref(input: TokenStream) -> TokenStream {
quote! {
_args_array[_arg_write_index] = _make_ref(
::std::ptr::NonNull::new(#input)
.ok_or_else(|| napi::Error::new(napi::Status::InvalidArg, "referenced ptr is null".to_owned()))?
)?;
_arg_write_index += 1;
}
}
struct ArgConversions {
pub args: Vec<TokenStream>,
pub arg_conversions: Vec<TokenStream>,
pub this_conversions: Vec<TokenStream>,
pub receiver_unwrap: TokenStream,
pub receiver_dependent_conversions: Vec<TokenStream>,
pub receiver_conversion: TokenStream,
pub refs: Vec<TokenStream>,
pub mut_ref_spans: Vec<Span>,
pub unsafe_: bool,
}
#[derive(Debug, PartialEq, Eq)]View on GitHub (pinned to 39bd1205e4)