neon-bindings/neon · error
Context must be a `&mut` reference.
Error message
Context must be a `&mut` reference.
What it means
check_constructor_context in crates/neon-macros/src/class/mod.rs requires the constructor's first argument to be a reference type (`syn::Type::Reference`). If the first parameter is neither a reference nor the caller opted out via `opts.context`, and the type still looks like a Neon context type (is_context_type), the macro rejects it: a context must be passed as `&mut Context`, not by value or as a smart pointer. This catches passing `FunctionContext` or `Cx` by value.
Solutions
- Change the first parameter to a mutable reference: `cx: &mut FunctionContext` (or the crate's context alias like `&mut Cx`)
- Never take a Neon context by value — contexts are always borrowed for the duration of the call
Example fix
// before
#[constructor]
fn new(cx: FunctionContext) -> JsResult<JsObject> { ... }
// after
#[constructor]
fn new(cx: &mut FunctionContext) -> JsResult<JsObject> { ... } Defensive patterns
Strategy: validation
Validate before calling
fn ensure_context_is_ref(first_arg: Option<&syn::FnArg>) -> Result<(), String> {
match first_arg {
Some(syn::FnArg::Typed(t)) => match &*t.ty {
syn::Type::Reference(_) => Ok(()),
_ => Err("context must be `&mut <Context>`, not by value".into()),
},
_ => Ok(()),
}
} Prevention
- Never take Neon context types by value; always `&mut`
- Copy signatures from Neon docs/examples verbatim
- Let the compiler name the type via inference where possible to avoid hand-written mistakes
When it happens
Trigger: First constructor parameter is a context type by value, e.g. `fn new(cx: FunctionContext)`, or a non-reference wrapper such as `Box<FunctionContext>`, while the `context` attribute is set or the type is detected as a context type.
Common situations: Forgetting the `&mut` when writing the signature from memory; upgrading Neon and copying an older by-value signature style; IDE auto-completing the type without the reference.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Constructor cannot have a `self` receiver
- Expected a context argument. Try removing the `context`…
- Only one `new` constructor is allowed in a class.
- Expected `&mut Cx` instead of a `Channel` reference.
- Context must be a `&mut` reference.
AI-assisted analysis of neon-bindings/neon@38960e4381 (2026-09-13).
Data as JSON: /api/errors/9606dd203266991c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/neon-macros/src/class/mod.rs:688
"Constructor cannot have a `self` receiver",
))
}
None if opts.context => {
return Err(syn::Error::new(
sig.inputs.span(),
"Expected a context argument. Try removing the `context` attribute.",
))
}
None => return Ok(false),
};
// Extract the reference type
let ty = match &*ty.ty {
syn::Type::Reference(ty) => ty,
// Context needs to be a reference
_ if opts.context || is_context_type(&ty.ty) => {
return Err(syn::Error::new(
ty.ty.span(),
"Context must be a `&mut` reference.",
))
}
_ => return Ok(false),
};
// Not a forced or inferred context
if !opts.context && !is_context_type(&ty.elem) {
return Ok(false);
}
// Context argument must be mutable
if ty.mutability.is_none() {
return Err(syn::Error::new(ty.span(), "Must be a `&mut` reference."));
}
View on GitHub (pinned to 38960e4381)