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

  1. Add the missing reference: change `cx: FunctionContext` to `mut cx: &mut FunctionContext` (or `&mut Cx`).
  2. Ensure the parameter is exactly a reference type (`syn::Type::Reference`) with `mut`.
  3. 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

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


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)