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

  1. Change the first parameter to a mutable reference: `cx: &mut FunctionContext` (or the crate's context alias like `&mut Cx`)
  2. 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

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


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)