{"record":{"id":"b94caf119d2c68ed","repo":"neon-bindings/neon","slug":"expected-an-owned-channel-instead-of-a-context-reference-mod","errorCode":null,"errorMessage":"Expected an owned `Channel` instead of a context reference.","messagePattern":"Expected an owned `Channel` instead of a context reference\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/neon-macros/src/export/function/mod.rs","lineNumber":270,"sourceCode":"fn check_channel(opts: &meta::Meta, sig: &syn::Signature) -> syn::Result<bool> {\n    // Extract the first argument\n    let ty = match first_arg(opts, sig)? {\n        Some(arg) => arg,\n        None => return Ok(false),\n    };\n\n    // Check the type\n    match &*ty.ty {\n        // Provided `&mut Channel` instead of `Channel`\n        syn::Type::Reference(ty) if opts.context || is_channel_type(&ty.elem) => {\n            Err(syn::Error::new(\n                ty.span(),\n                \"Expected an owned `Channel` instead of a reference.\",\n            ))\n        }\n\n        // Provided a `&mut Cx` instead of a `Channel`\n        syn::Type::Reference(ty) if is_context_type(&ty.elem) => Err(syn::Error::new(\n            ty.elem.span(),\n            \"Expected an owned `Channel` instead of a context reference.\",\n        )),\n\n        // Found a `Channel`\n        _ if opts.context || is_channel_type(&ty.ty) => Ok(true),\n\n        // Tried to use an owned `Cx`\n        _ if is_context_type(&ty.ty) => Err(syn::Error::new(\n            ty.ty.span(),\n            \"Context is not available in async functions. Try a `Channel` instead.\",\n        )),\n\n        _ => Ok(false),\n    }\n}\n\n// Extract the first argument, that may be a context, of a function","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/neon-bindings/neon/blob/38960e4381d9ad13b551cdf2d261f609167c9bc2/crates/neon-macros/src/export/function/mod.rs#L252-L288","documentation":"The export macro detected that a parameter declared as `&mut Cx` (or another context reference type) was expected to be a `Channel` — e.g. under an async/queued signature where Neon accepts an owned `Channel` instead of the execution context. Unlike error 41 (a reference to a channel type), this variant fires when the referenced type is a *context* type, giving a more specific message pointing the developer at the real type they misused.","triggerScenarios":"Writing `fn f(cx: &mut Cx)` where the macro requires an owned `Channel` (e.g. an async fn signature matched by `check_channel` when `is_context_type(&ty.elem)`), or `#[context]`-annotated param whose type is a context reference but the caller expected a Channel.","commonSituations":"Using the familiar `&mut Cx` context parameter in an async fn, where Neon only supports a `Channel`; mixing up context and channel conventions after reading docs for synchronous exports.","solutions":["Replace `&mut Cx` with an owned `Channel` parameter: `fn f(ch: Channel)`.","If context access is truly needed, make the function synchronous rather than async/queued.","If it should be a context param, add the `context` attribute so `check_context` (which allows `&mut` context refs) validates it instead."],"exampleFix":"// before\n#[neon::export]\nasync fn work(cx: &mut Cx) -> JsResult<JsNumber> { /* ... */ }\n\n// after\n#[neon::export]\nasync fn work(ch: Channel) -> JsResult<JsNumber> { /* ... */ }","handlingStrategy":"validation","validationCode":"// Async/queued exports take Channel, not context refs:\nfn valid_async_export(ch: neon::event::Channel) {} // ok\n// fn invalid_async_export(cx: &mut Cx) {} // rejected by check_channel","typeGuard":null,"tryCatchPattern":null,"preventionTips":["For async exports, take `Channel` as the parameter, never `&mut Cx`.","Check whether you want the `context` attribute (which routes to check_context) before writing a context-typed param.","Review Neon's async section: the JS context is unavailable; only a Channel can hop back."],"tags":["rust","neon","compile-time","macro","async","channel","context"],"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"}