neon-bindings/neon · error
Context must be a `&mut` reference.
Error message
Context must be a `&mut` reference.
What it means
Compile-time error from Neon's context check: a parameter in the context position was neither a reference type nor otherwise valid — the type is treated as a context type (either `opts.context` is set or `is_context_type()` matched) but it is not a `&mut` reference. Neon requires the execution context argument to be a mutable reference (`&mut Cx`, `&mut FunctionContext`, etc.).
Solutions
- Add the missing reference: change `cx: FunctionContext` to `mut cx: &mut FunctionContext` (or `&mut Cx`).
- Ensure the parameter is exactly a reference type (`syn::Type::Reference`) with `mut`.
- Check that you did not accidentally wrap the context in another type (e.g. `Option<...>`, tuples) which is not a reference.
Example fix
// before
fn my_fn(cx: FunctionContext) -> JsResult<JsNumber> { ... }
// after
fn my_fn(mut cx: FunctionContext) -> JsResult<JsNumber> { ... }
// (macro-generated signature takes `&mut FunctionContext`; write the fn body accordingly) Defensive patterns
Strategy: type-guard
Type guard
// Ensure the context parameter is written as a mutable reference type:
fn valid_context(cx: &mut neon::context::FunctionContext) {}
// A bare (non-reference) context type like `FunctionContext` will fail this check. Try / catch
// Compile-time error; pattern for CI gating: // if `cargo check` output contains "Context must be a `&mut` reference." // then fix the parameter to `&mut ...` before merging.
Prevention
- Always write the context parameter as `mut cx: &mut <ContextType>`.
- Never pass contexts by value.
- Run `cargo check` immediately after signature edits.
When it happens
Trigger: Declaring a context-like parameter by value or as an immutable binding, e.g. `fn f(cx: FunctionContext)` or `fn f(cx: Cx)`, when the macro expects the context slot to be a reference type.
Common situations: Porting signatures from other NAPI/Rust-Node frameworks that take contexts by value, dropping the `&mut` when hand-writing the signature, or misremembering whether `Cx` is passed by 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
- Context must be a `&mut` reference.
- Expected `&mut Cx` instead of a `Channel` reference.
- Expected `&mut Cx` instead of `Channel`.
- Expected an owned `Channel` instead of a context reference.
- Context is not available in async functions. Try a…
AI-assisted analysis of neon-bindings/neon@38960e4381 (2026-09-13).
Data as JSON: /api/errors/7b77ca86ef21a570.
Report an issue: GitHub.
Appendix: source
Thrown at crates/neon-macros/src/export/function/mod.rs:216
None => return Ok(false),
};
// Extract the reference type
let ty = match &*ty.ty {
// Tried to use a borrowed Channel
syn::Type::Reference(ty) if !opts.context && is_channel_type(&ty.elem) => {
return Err(syn::Error::new(
ty.elem.span(),
"Expected `&mut Cx` instead of a `Channel` reference.",
))
}
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.",
))
}
// Hint that `Channel` should be swapped for `&mut Cx`
_ if is_channel_type(&ty.ty) => {
return Err(syn::Error::new(
ty.ty.span(),
"Expected `&mut Cx` instead of `Channel`.",
))
}
_ => return Ok(false),
};
// Not a forced or inferred context
if !opts.context && !is_context_type(&ty.elem) {
return Ok(false);View on GitHub (pinned to 38960e4381)