{"record":{"id":"d3dd110e2d6dfe04","repo":"neon-bindings/neon","slug":"cannot-combine-async-fn-with-neon-async-attribute","errorCode":null,"errorMessage":"Cannot combine `async fn` with `#[neon(async)]` attribute","messagePattern":"Cannot combine `async fn` with `#\\[neon\\(async\\)\\]` attribute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/neon-macros/src/class/mod.rs","lineNumber":532,"sourceCode":"\n    ident == \"Channel\"\n}\n\n// Extract the identifier from the last segment of a type's path\nfn type_path_ident(ty: &syn::Type) -> Option<&syn::Ident> {\n    let segment = match ty {\n        syn::Type::Path(ty) => ty.path.segments.last()?,\n        _ => return None,\n    };\n\n    Some(&segment.ident)\n}\n\n// Validate method attributes for common errors and conflicts\nfn validate_method_attributes(meta: &meta::Meta, sig: &syn::Signature) -> syn::Result<()> {\n    // Check for conflicting async attributes\n    if matches!(meta.kind, meta::Kind::AsyncFn) && matches!(meta.kind, meta::Kind::Async) {\n        return Err(syn::Error::new(\n            sig.span(),\n            \"Cannot combine `async fn` with `#[neon(async)]` attribute\",\n        ));\n    }\n\n    // Check for async + task conflict\n    if matches!(meta.kind, meta::Kind::AsyncFn | meta::Kind::Async)\n        && matches!(meta.kind, meta::Kind::Task)\n    {\n        return Err(syn::Error::new(\n            sig.span(),\n            \"Cannot combine async method with `#[neon(task)]` attribute\",\n        ));\n    }\n\n    // Validate that async fn and task methods take self by value\n    if matches!(meta.kind, meta::Kind::AsyncFn | meta::Kind::Task) {\n        if let Some(syn::FnArg::Receiver(receiver)) = sig.inputs.first() {","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/neon-bindings/neon/blob/38960e4381d9ad13b551cdf2d261f609167c9bc2/crates/neon-macros/src/class/mod.rs#L514-L550","documentation":"Compile-time error from Neon's `#[neon]` class macro in `validate_method_attributes`. It fires when a method is declared `async fn` (macro kind `AsyncFn`) and is also marked with the `#[neon(async)]` attribute (kind `Async`). Both spellings request the same async treatment, so combining them is redundant and ambiguous — the macro rejects the declaration instead of guessing.","triggerScenarios":"Annotating a method that is already declared `async fn` with `#[neon(async)]`, e.g. `#[neon(async)] async fn run(&self, ...)`. (Note: with this macro implementation both `Kind::AsyncFn` and `Kind::Async` must be present simultaneously to trigger the error.)","commonSituations":"Adding `#[neon(async)]` for explicitness on an already-`async fn` method; copy-pasting attributes from a non-async method when converting it to `async fn`; mixing examples from different Neon versions that use different async spellings.","solutions":["Remove the `#[neon(async)]` attribute and keep `async fn`.","Alternatively, keep `#[neon(async)]` and drop the `async` keyword if the intended style is attribute-driven (verify against your Neon version's supported forms).","Check the Neon docs for the canonical way to declare async methods in your version and use only one mechanism."],"exampleFix":"// before\n#[neon(async)]\nasync fn run(&self, mut cx: Channel) -> JsResult<JsUndefined> {\n    ...\n}\n\n// after\nasync fn run(&self, mut cx: Channel) -> JsResult<JsUndefined> {\n    ...\n}","handlingStrategy":"validation","validationCode":"// Reject declarations that both use `async fn` and #[neon(async)].\nfn validate_async_spelling(has_async_fn: bool, has_neon_async_attr: bool) -> Result<(), String> {\n    if has_async_fn && has_neon_async_attr {\n        return Err(\"use either `async fn` or `#[neon(async)]`, not both\".into());\n    }\n    Ok(())\n}","typeGuard":"fn is_unambiguous_async(has_async_fn: bool, has_neon_async_attr: bool) -> bool {\n    has_async_fn ^ has_neon_async_attr\n}","tryCatchPattern":null,"preventionTips":["Pick one async declaration style for the whole codebase (preferred: plain `async fn`) and enforce it in review.","When converting a method to `async fn`, remove any existing `#[neon(async)]` attribute in the same edit.","Consult the Neon docs for your pinned version to confirm which async spelling it supports."],"tags":["rust","proc-macro","neon","async","attribute-conflict","compile-time"],"backgroundTag":"mutually-exclusive-options","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"}