{"record":{"id":"a1a6f5d31bc0d1b6","repo":"neon-bindings/neon","slug":"cannot-combine-async-method-with-neon-task-attribute","errorCode":null,"errorMessage":"Cannot combine async method with `#[neon(task)]` attribute","messagePattern":"Cannot combine async method with `#\\[neon\\(task\\)\\]` attribute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/neon-macros/src/class/mod.rs","lineNumber":542,"sourceCode":"\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() {\n            if receiver.reference.is_some() {\n                // This is &self or &mut self, but we need self by value\n                let method_type = if matches!(meta.kind, meta::Kind::AsyncFn) {\n                    \"Async functions\"\n                } else {\n                    \"Task methods\"\n                };\n                let reason = if matches!(meta.kind, meta::Kind::AsyncFn) {\n                    \"This is required because async functions capture `self` in the Future, which must be `'static` for spawning.\"\n                } else {","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/neon-bindings/neon/blob/38960e4381d9ad13b551cdf2d261f609167c9bc2/crates/neon-macros/src/class/mod.rs#L524-L560","documentation":"The `#[neon]` macro rejects class methods declared `async` that also carry the `#[neon(task)]` attribute. An async fn is already executed on a separate task internally, so wrapping it again as an explicit task is contradictory and unsupported by the macro's code generation.","triggerScenarios":"Annotating a single class method with both forms: `#[neon(task)]` (or the combined `#[neon(task = ...)]`) on a method whose signature is `async fn`, e.g. `#[neon] impl Foo { #[neon(task)] async fn work(&self) -> ... }`.","commonSituations":"Developers migrate a sync task method to async and forget to remove `#[neon(task)]`; copy-pasting a task-based example and converting it to `async fn`; refactorings that add `async` for await-based I/O without revisiting the attribute list.","solutions":["Remove the `#[neon(task)]` attribute and keep the method `async fn` (async methods are already spawned as tasks).","Or keep `#[neon(task)]` and remove `async`, implementing the work synchronously in the task's `run` method.","Ensure the method takes `self` by value, since both async and task methods require it."],"exampleFix":"// before\n#[neon]\nimpl Foo {\n    #[neon(task)]\n    async fn compute(&self) -> JsResult<JsNumber> { ... }\n}\n\n// after\n#[neon]\nimpl Foo {\n    async fn compute(&self) -> JsResult<JsNumber> { ... }\n}","handlingStrategy":"validation","validationCode":"// Compile-time macro check; guard at code review / CI\nfn assert_no_task_on_async(attrs: &[&str], is_async: bool) -> Result<(), String> {\n    if is_async && attrs.contains(&\"task\") {\n        return Err(\"remove #[neon(task)] from async methods\".into());\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember: `async fn` in a #[neon] impl already implies task-based execution.","Run `cargo check` before committing; this error surfaces immediately at macro expansion.","When converting sync task methods to async, delete the `#[neon(task)]` attribute in the same commit."],"tags":["rust","neon","macros","async","attribute-conflict"],"backgroundTag":"mutually-exclusive-flags","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"}