{"record":{"id":"b7779d15b4454aaa","repo":"neon-bindings/neon","slug":"context-parameters-must-be-a-mut-reference-try-mut","errorCode":null,"errorMessage":"Context parameters must be a `&mut` reference. Try `&mut FunctionContext` or `&mut Cx`.","messagePattern":"Context parameters must be a `&mut` reference\\. Try `&mut FunctionContext` or `&mut Cx`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/neon-macros/src/class/mod.rs","lineNumber":402,"sourceCode":"        Some(arg) => arg,\n        None => return Ok(false),\n    };\n\n    // Extract the reference type\n    let ty = match &*ty.ty {\n        // Tried to use a borrowed Channel\n        syn::Type::Reference(ty) if !opts.context && is_channel_type(&ty.elem) => {\n            return Err(syn::Error::new(\n                ty.elem.span(),\n                \"Expected `&mut Cx` instead of a `Channel` reference.\",\n            ))\n        }\n\n        syn::Type::Reference(ty) => ty,\n\n        // Context needs to be a reference\n        _ if opts.context || is_context_type(&ty.ty) => {\n            return Err(syn::Error::new(\n                ty.ty.span(),\n                \"Context parameters must be a `&mut` reference. Try `&mut FunctionContext` or `&mut Cx`.\",\n            ))\n        }\n\n        // Hint that `Channel` should be swapped for `&mut Cx`\n        _ if is_channel_type(&ty.ty) => {\n            return Err(syn::Error::new(\n                ty.ty.span(),\n                \"Unexpected `Channel` in sync method. Use `&mut FunctionContext` for sync methods, or `Channel` in async/task methods.\",\n            ))\n        }\n\n        _ => return Ok(false),\n    };\n\n    // Not a forced or inferred context\n    if !opts.context && !is_context_type(&ty.elem) {","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/neon-bindings/neon/blob/38960e4381d9ad13b551cdf2d261f609167c9bc2/crates/neon-macros/src/class/mod.rs#L384-L420","documentation":"A neon class method or exported function declared a context parameter by value or as a non-reference type (e.g. `FunctionContext`, `Cx`). Contexts in neon must always be passed as mutable references (`&mut FunctionContext`, `&mut Cx`) because they borrow the Node execution environment. The proc macro enforces this and fails the compilation otherwise.","triggerScenarios":"Declaring a method parameter whose type is a context type (`FunctionContext`, `Cx`, `Context`, etc.) but not a `&mut` reference — e.g. `fn f(cx: FunctionContext)` or `fn f(cx: &FunctionContext)` — either explicitly or via `#[neon(context)]` on a method whose first non-self arg is not a `&mut` reference.","commonSituations":"Writing a Rust function signature by habit instead of copying neon's `fn(cx: &mut FunctionContext)` idiom; converting an internal helper into an exported method without adjusting the signature; upgrading from older neon versions with different context conventions.","solutions":["Change the parameter to a mutable reference: `&mut FunctionContext` (for exported functions) or `&mut Cx` (for class methods).","Add the `mut` if you already have a reference: `&FunctionContext` -> `&mut FunctionContext`.","If the type is not meant to be a context at all, rename it / use a different type so the macro does not infer a context parameter.","Check the `#[neon]`/`#[neon(context)]` attribute: if it forces a context parameter, the first non-self argument must satisfy the `&mut` reference requirement."],"exampleFix":"// before\nfn log_event(cx: FunctionContext, msg: String) -> JsResult<JsUndefined> { ... }\n\n// after\nfn log_event(cx: &mut FunctionContext, msg: String) -> JsResult<JsUndefined> { ... }","handlingStrategy":"type-guard","validationCode":"// Validate exported fn/method signatures before deriving:\nfn validate_context_param(ty: &str) -> Result<(), String> {\n    if [\"FunctionContext\", \"Cx\"].iter().any(|c| ty.contains(c)) && !ty.starts_with(\"&mut \") {\n        return Err(format!(\"context `{}` must be `&mut {}`\", ty, ty));\n    }\n    Ok(())\n}","typeGuard":"fn is_valid_context_arg(ty: &syn::Type) -> bool {\n    matches!(ty, syn::Type::Reference(r)\n        if r.mutability.is_some() && [\"Cx\", \"FunctionContext\"].iter().any(|c| type_name(&r.elem).contains(c)))\n}","tryCatchPattern":null,"preventionTips":["Always write exported signatures as `fn(cx: &mut FunctionContext, ...)` / `fn(&self, cx: &mut Cx, ...)`","Never take contexts by value or as `&` — neon requires `&mut`","Run `cargo check` before committing macro-exported code","Keep a snippet/template of valid neon method signatures in the project docs"],"tags":["rust","neon","compile-time","macro","napi"],"backgroundTag":"type-mismatch","analyzedSha":"38960e4381d9ad13b551cdf2d261f609167c9bc2","analyzedAt":"2026-09-13T09:05:33.640Z","contentChangedAt":"2026-09-13T09:05:33.640Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}