dotnet/BenchmarkDotNet · error · NotSupportedException
async void is not supported by design
Error message
async void is not supported by design
What it means
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.
Source
Thrown at src/BenchmarkDotNet/Code/CodeGenerator.cs:133
if (method.ReturnType.IsAwaitable(out var awaitableInfo))
{
if (benchmark.Job.ResolveValue(RunMode.ConsumeTasksSynchronouslyCharacteristic, EnvironmentResolver.Instance)
&& AwaitHelper.IsBuiltInTaskType(method.ReturnType))
{
return new SyncTaskDeclarationsProvider(benchmark);
}
return new AsyncDeclarationsProvider(benchmark, awaitableInfo.ResultType);
}
if (method.ReturnType.IsAsyncEnumerable(out var asyncEnumerableInfo))
{
return new AsyncEnumerableDeclarationsProvider(benchmark, asyncEnumerableInfo.ItemType, asyncEnumerableInfo.MoveNextAsyncMethod.ReturnType);
}
if (method.ReturnType == typeof(void) && method.HasAttribute<AsyncStateMachineAttribute>())
{
throw new NotSupportedException("async void is not supported by design");
}
return new SyncDeclarationsProvider(benchmark);
}
// internal for tests
internal static string GetParamsContent(BenchmarkCase benchmarkCase)
=> string.Join(
string.Empty,
benchmarkCase.Parameters.Items
.Where(parameter => !parameter.IsArgument)
.Select(parameter => $"{(parameter.IsStatic ? benchmarkCase.Descriptor.Type.GetCorrectCSharpTypeName() : "base")}.{parameter.Name} = {parameter.ToSourceCode()};"));
internal static string GetCancellationTokenAssignment(BenchmarkCase benchmarkCase)
{
var targetType = benchmarkCase.Descriptor.Type;
var cancellationTokenMembers = new System.Collections.Generic.List<string>();View on GitHub (pinned to b515068b61)
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.
Example fix
// before
[Benchmark]
public async void Foo() { await DoWork(); }
// after
[Benchmark]
public async Task Foo() { await DoWork(); } Defensive patterns
Strategy: validation
Validate before calling
// Compile-time: never declare async void benchmarks. Static guard example:
static bool IsValidBenchmarkMethod(MethodInfo m)
=> !(m.ReturnType == typeof(void) && m.GetCustomAttribute<AsyncStateMachineAttribute>() != null); Type guard
// rejects async void benchmark methods
static bool IsNotAsyncVoid(MethodInfo m)
=> !(m.ReturnType == typeof(void) && m.GetCustomAttribute<AsyncStateMachineAttribute>() is not null); Try / catch
try { CodeGenerator.GetDeclarationsProvider(benchmark); }
catch (NotSupportedException ex) when (ex.Message.Contains("async void"))
{
// surface a build error telling the user to change the return type to Task
} Prevention
- 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.
When it happens
Trigger: Declaring a benchmark as `[Benchmark] public async void Foo() { await ... }`. The compiler emits AsyncStateMachineAttribute on a void-returning async method, hitting the guard.
Common situations: Copying an async helper as a benchmark without changing its signature, or assuming async benchmarks can be void like event handlers.
Related errors
- Custom factory must have a public parameterless constructor
- Platform {platform} is not supported
- Runtime {runtimeId} is not supported
- {platform} is not supported
- {System.Runtime.InteropServices.RuntimeInformation.OSDescrip
AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13).
Data as JSON: /api/errors/7536495791859dbb.
Report an issue: GitHub.