{"record":{"id":"7536495791859dbb","repo":"dotnet/BenchmarkDotNet","slug":"async-void-is-not-supported-by-design","errorCode":null,"errorMessage":"async void is not supported by design","messagePattern":"async void is not supported by design","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/BenchmarkDotNet/Code/CodeGenerator.cs","lineNumber":133,"sourceCode":"\n            if (method.ReturnType.IsAwaitable(out var awaitableInfo))\n            {\n                if (benchmark.Job.ResolveValue(RunMode.ConsumeTasksSynchronouslyCharacteristic, EnvironmentResolver.Instance)\n                    && AwaitHelper.IsBuiltInTaskType(method.ReturnType))\n                {\n                    return new SyncTaskDeclarationsProvider(benchmark);\n                }\n                return new AsyncDeclarationsProvider(benchmark, awaitableInfo.ResultType);\n            }\n\n            if (method.ReturnType.IsAsyncEnumerable(out var asyncEnumerableInfo))\n            {\n                return new AsyncEnumerableDeclarationsProvider(benchmark, asyncEnumerableInfo.ItemType, asyncEnumerableInfo.MoveNextAsyncMethod.ReturnType);\n            }\n\n            if (method.ReturnType == typeof(void) && method.HasAttribute<AsyncStateMachineAttribute>())\n            {\n                throw new NotSupportedException(\"async void is not supported by design\");\n            }\n\n            return new SyncDeclarationsProvider(benchmark);\n        }\n\n        // internal for tests\n\n        internal static string GetParamsContent(BenchmarkCase benchmarkCase)\n            => string.Join(\n                string.Empty,\n                benchmarkCase.Parameters.Items\n                    .Where(parameter => !parameter.IsArgument)\n                    .Select(parameter => $\"{(parameter.IsStatic ? benchmarkCase.Descriptor.Type.GetCorrectCSharpTypeName() : \"base\")}.{parameter.Name} = {parameter.ToSourceCode()};\"));\n\n        internal static string GetCancellationTokenAssignment(BenchmarkCase benchmarkCase)\n        {\n            var targetType = benchmarkCase.Descriptor.Type;\n            var cancellationTokenMembers = new System.Collections.Generic.List<string>();","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/dotnet/BenchmarkDotNet/blob/b515068b61ad1c9c9aa938b8ece4af1e7d6d85a3/src/BenchmarkDotNet/Code/CodeGenerator.cs#L115-L151","documentation":"During harness source generation, CodeGenerator inspects the benchmark method's return type. A method with void return type but the AsyncStateMachineAttribute is an `async void` method, which BenchmarkDotNet deliberately does not support: the engine cannot await or measure it because async void gives no handle to the completion. NotSupportedException is thrown at build time.","triggerScenarios":"Declaring a benchmark as `[Benchmark] public async void Foo() { await ... }`. The compiler emits AsyncStateMachineAttribute on a void-returning async method, hitting the guard.","commonSituations":"Copying an async helper as a benchmark without changing its signature, or assuming async benchmarks can be void like event handlers.","solutions":["Change the benchmark to return Task (or ValueTask): `[Benchmark] public async Task Foo()`. BDN supports Task/ValueTask and IAsyncEnumerable<T>.","If the work is genuinely fire-and-forget, wrap it so it returns Task and await inside.","Remove async and run synchronously if async measurement is not required.","Ensure no base/overload accidentally reintroduces an async void signature."],"exampleFix":"// before\n[Benchmark]\npublic async void Foo() { await DoWork(); }\n\n// after\n[Benchmark]\npublic async Task Foo() { await DoWork(); }","handlingStrategy":"validation","validationCode":"// Compile-time: never declare async void benchmarks. Static guard example:\nstatic bool IsValidBenchmarkMethod(MethodInfo m)\n    => !(m.ReturnType == typeof(void) && m.GetCustomAttribute<AsyncStateMachineAttribute>() != null);","typeGuard":"// rejects async void benchmark methods\nstatic bool IsNotAsyncVoid(MethodInfo m)\n    => !(m.ReturnType == typeof(void) && m.GetCustomAttribute<AsyncStateMachineAttribute>() is not null);","tryCatchPattern":"try { CodeGenerator.GetDeclarationsProvider(benchmark); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"async void\"))\n{\n    // surface a build error telling the user to change the return type to Task\n}","preventionTips":["Always return Task or ValueTask from async benchmarks (or IAsyncEnumerable<T>).","Add a source-generator/analyser check for `[Benchmark] async void` to fail fast at edit time.","Do not reuse event-handler-style async void signatures for benchmarks."],"tags":["async","benchmark-method","code-generation","notsupported","by-design"],"backgroundTag":null,"analyzedSha":"b515068b61ad1c9c9aa938b8ece4af1e7d6d85a3","analyzedAt":"2026-08-13T19:12:24.196Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}