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

  1. Change the method signature from 'async void' to 'async Task'.
  2. If the method must remain async void for UI reasons, add a separate async Task wrapper method and enqueue that.
  3. 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

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


AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13). Data as JSON: /api/errors/4fa74c377f3f667a. Report an issue: GitHub.