{"record":{"id":"660c64c721a4a1a4","repo":"neon-bindings/neon","slug":"expected-mut-cx-instead-of-channel","errorCode":null,"errorMessage":"Expected `&mut Cx` instead of `Channel`.","messagePattern":"Expected `&mut Cx` instead of `Channel`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/neon-macros/src/export/function/mod.rs","lineNumber":224,"sourceCode":"                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 must be a `&mut` reference.\",\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                \"Expected `&mut Cx` instead of `Channel`.\",\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) {\n        return Ok(false);\n    }\n\n    // Context argument must be mutable\n    if ty.mutability.is_none() {\n        return Err(syn::Error::new(ty.span(), \"Must be a `&mut` reference.\"));\n    }\n\n    // All tests passed!","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/neon-bindings/neon/blob/38960e4381d9ad13b551cdf2d261f609167c9bc2/crates/neon-macros/src/export/function/mod.rs#L206-L242","documentation":"Compile-time error from Neon's context check: a parameter in the context position was an owned `Channel` (by value, not a reference) where a mutable context reference is required. Neon explicitly hints that `Channel` should be swapped for `&mut Cx`.","triggerScenarios":"Declaring `fn my_fn(channel: Channel)` — an un-borrowed `Channel` type in the parameter list that `is_channel_type()` matches, in the context slot of an exported function.","commonSituations":"Developers copying `Channel` from async/threading examples into the context parameter position, or trying to receive a Channel as the first argument of an exported function instead of the context.","solutions":["Replace the `Channel` parameter with `mut cx: &mut Cx` / `&mut FunctionContext`.","If a Channel is needed for background work, obtain it inside the function via `cx.channel()`.","If you need a Channel as data, accept it through a different mechanism (e.g. stored in a struct passed as an argument), not in the context position."],"exampleFix":"// before\nfn my_fn(channel: Channel) -> JsResult<JsUndefined> { ... }\n// after\nfn my_fn(mut cx: &mut FunctionContext) -> JsResult<JsUndefined> {\n    let channel = cx.channel();\n    ...\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Ensure no parameter in the context position is an owned Channel:\n// bad: fn f(ch: Channel)\n// good: fn f(mut cx: &mut FunctionContext)\nfn valid_context(cx: &mut neon::context::FunctionContext) {}","tryCatchPattern":"// Compile-time error; pattern for CI gating:\n// if `cargo check` output contains \"Expected `&mut Cx` instead of `Channel`.\"\n// then replace the Channel parameter with a context reference.","preventionTips":["Treat the first context-slot parameter as reserved for `&mut Cx`/`&mut FunctionContext`.","Create Channels inside the function via `cx.channel()` instead of taking them as parameters.","Review Neon async examples for correct Channel usage patterns."],"tags":["rust","neon","proc-macro","type-mismatch"],"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"}