HangfireIO/Hangfire · error · NotSupportedException
Async void methods are not supported. Use async Task instead
Error message
Async void methods are not supported. Use async Task instead.
What it means
NotSupportedException thrown by Job.Validate when the method has a void return type and is decorated (or detected via AsyncStateMachineAttribute) as an async method — i.e., an 'async void' method. Hangfire cannot await async void methods because their continuations are fire-and-forget (the awaiter is the SynchronizationContext, not the caller), so the server performer would have no way to know when the job completed or failed. The fix is to return Task (or Task<T>) instead.
Source
Thrown at src/Hangfire.Core/Common/Job.cs:500
throw new NotSupportedException("Job method can not contain unassigned generic type parameters.");
}
if (method.DeclaringType == null)
{
throw new NotSupportedException("Global methods are not supported. Use class methods instead.");
}
if (!method.DeclaringType.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
{
throw new ArgumentException(
$"The type `{method.DeclaringType}` must be derived from the `{type}` type.",
typeParameterName);
}
if (method.ReturnType == typeof(void) &&
AsyncStateMachineAttributeCache.GetOrAdd(method, static m => m.GetCustomAttribute<AsyncStateMachineAttribute>()) != null)
{
throw new NotSupportedException("Async void methods are not supported. Use async Task instead.");
}
var parameters = method.GetParameters();
if (parameters.Length != argumentCount)
{
throw new ArgumentException(
"Argument count must be equal to method parameter count.",
argumentParameterName);
}
foreach (var parameter in parameters)
{
// There is no guarantee that specified method will be invoked
// in the same process. Therefore, output parameters and parameters
// passed by reference are not supported.
if (parameter.IsOut)View on GitHub (pinned to c236dd0f93)
Solutions
- Change the method signature from 'async void' to 'async Task'.
- If the method must remain async void for UI reasons, add a separate async Task wrapper method and enqueue that.
- Audit event-handler-style methods before enqueuing.
Example fix
// before — async void, unsupported
public class Worker {
public async void DoWork() { await Task.Delay(100); }
}
BackgroundJob.Enqueue<Worker>(x => x.DoWork());
// after — async Task
public class Worker {
public async Task DoWork() { await Task.Delay(100); }
}
BackgroundJob.Enqueue<Worker>(x => x.DoWork()); Defensive patterns
Strategy: validation
Validate before calling
var isAsyncVoid = method.ReturnType == typeof(void)
&& method.GetCustomAttribute<AsyncStateMachineAttribute>() != null;
if (isAsyncVoid)
throw new NotSupportedException("Job method is 'async void'; change the return type to Task."); Type guard
public static bool IsAsyncTaskMethod(MethodInfo m)
=> m != null && (m.ReturnType == typeof(Task) || m.ReturnType.IsGenericType && m.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)); Try / catch
try { BackgroundJob.Enqueue<T>(x => x.Work()); }
catch (NotSupportedException ex) when (ex.Message.Contains("Async void")) { /* change 'async void' to 'async Task' */ } Prevention
- Always declare async job methods as 'async Task' or 'async Task<T>', never 'async void'.
- Audit event-handler-style methods before converting them to jobs.
- Add a unit test scanning job methods for [AsyncStateMachine] combined with void return.
When it happens
Trigger: Enqueuing () => service.DoWorkAsync() where DoWorkAsync is declared as 'async void DoWorkAsync()'. Detection uses AsyncStateMachineAttributeCache to find [AsyncStateMachine] on the method combined with a void return type.
Common situations: WPF/WinForms event handlers (which are async void) mistakenly enqueued as jobs; copy-pasting an async event handler into a job method; refactoring an async Task method to async void during cleanup.
Related errors
- Only public methods can be invoked in the background. Ensure
- Job method can not contain unassigned generic type parameter
- Global methods are not supported. Use class methods instead.
- Output parameters are not supported: there is no guarantee t
- Parameters, passed by reference, are not supported: there is
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/4fa74c377f3f667a.
Report an issue: GitHub.