neon-bindings/neon · error
Expected `&mut Cx` instead of a `Channel` reference.
Error message
Expected `&mut Cx` instead of a `Channel` reference.
What it means
Compile-time error from Neon's `#[neon] fn` macro's context-type check. A function parameter was declared as a borrowed `&Channel` (or reference to Channel), but Neon requires the execution context parameter to be `&mut Cx`. Channels cannot be used as a borrowed context argument.
Solutions
- Change the parameter to a mutable context reference: `fn my_fn(mut cx: &mut Cx)` (or `FunctionContext`).
- If you need a Channel for async work, create/obtain it inside the function from the context (`cx.channel()`), not as a parameter type.
- Do not wrap `Channel` in a plain borrow; if a stored Channel is needed, take it as an owned/moved argument or via `JsFunction` arguments, not as the context slot.
Example fix
// before
fn my_fn(channel: &Channel) -> JsResult<JsUndefined> { ... }
// after
fn my_fn(mut cx: &mut FunctionContext) -> JsResult<JsUndefined> {
let channel = cx.channel();
...
} Defensive patterns
Strategy: type-guard
Type guard
// Ensure the context parameter is a mutable reference, never a Channel reference:
fn uses_valid_context(cx: &mut neon::context::FunctionContext) {}
// Prefer `&mut Cx`/`&mut FunctionContext` for the first parameter; obtain channels via cx.channel(). Try / catch
// Compile-time error; pattern for CI gating: // if `cargo check` output contains "Expected `&mut Cx` instead of a `Channel` reference." // then fail the build with a pointer to the offending fn signature.
Prevention
- Never use `Channel` (borrowed or owned) in the context parameter position; use `&mut Cx` or `&mut FunctionContext`.
- Get channels inside the function body with `cx.channel()`.
- Keep exported function signatures consistent with Neon examples and run `cargo check` in CI.
When it happens
Trigger: Declaring a Neon exported function like `fn my_fn(mut cx: &Channel)` or taking `&Channel` as a parameter where the macro expects a context type — specifically when the parameter is a `Type::Reference` whose element `is_channel_type()` and no `#[context]`-style opts flag is set.
Common situations: Developers trying to pass a Channel to background tasks directly as an argument type, confusing `Channel` with `Cx`/`FunctionContext`, or copying signatures from async examples that spawn channels elsewhere.
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.
- Context must be a `&mut` 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/d05309dd0294b902.
Report an issue: GitHub.
Appendix: source
Thrown at crates/neon-macros/src/export/function/mod.rs:205
// Checks if a _sync_ function has a context argument and if it is valid
// * If the `context` attribute is included, must be at least one argument
// * Inferred to be context if named `FunctionContext` or `Cx`
// * Context argument must be a `&mut` reference
// * First argument must not be `Channel`
// * Must not be a `self` receiver
fn check_context(opts: &meta::Meta, sig: &syn::Signature) -> syn::Result<bool> {
// Extract the first argument
let ty = match first_arg(opts, sig)? {
Some(arg) => arg,
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(View on GitHub (pinned to 38960e4381)