{"record":{"id":"4fa74c377f3f667a","repo":"HangfireIO/Hangfire","slug":"async-void-methods-are-not-supported-use-async-ta","errorCode":null,"errorMessage":"Async void methods are not supported. Use async Task instead.","messagePattern":"Async void methods are not supported\\. Use async Task instead\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Common/Job.cs","lineNumber":500,"sourceCode":"                throw new NotSupportedException(\"Job method can not contain unassigned generic type parameters.\");\n            }\n\n            if (method.DeclaringType == null)\n            {\n                throw new NotSupportedException(\"Global methods are not supported. Use class methods instead.\");\n            }\n\n            if (!method.DeclaringType.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))\n            {\n                throw new ArgumentException(\n                    $\"The type `{method.DeclaringType}` must be derived from the `{type}` type.\",\n                    typeParameterName);\n            }\n\n            if (method.ReturnType == typeof(void) &&\n                AsyncStateMachineAttributeCache.GetOrAdd(method, static m => m.GetCustomAttribute<AsyncStateMachineAttribute>()) != null)\n            {\n                throw new NotSupportedException(\"Async void methods are not supported. Use async Task instead.\");\n            }\n\n            var parameters = method.GetParameters();\n\n            if (parameters.Length != argumentCount)\n            {\n                throw new ArgumentException(\n                    \"Argument count must be equal to method parameter count.\",\n                    argumentParameterName);\n            }\n\n            foreach (var parameter in parameters)\n            {\n                // There is no guarantee that specified method will be invoked\n                // in the same process. Therefore, output parameters and parameters\n                // passed by reference are not supported.\n\n                if (parameter.IsOut)","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Common/Job.cs#L482-L518","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — async void, unsupported\npublic class Worker {\n    public async void DoWork() { await Task.Delay(100); }\n}\nBackgroundJob.Enqueue<Worker>(x => x.DoWork());\n\n// after — async Task\npublic class Worker {\n    public async Task DoWork() { await Task.Delay(100); }\n}\nBackgroundJob.Enqueue<Worker>(x => x.DoWork());","handlingStrategy":"validation","validationCode":"var isAsyncVoid = method.ReturnType == typeof(void)\n    && method.GetCustomAttribute<AsyncStateMachineAttribute>() != null;\nif (isAsyncVoid)\n    throw new NotSupportedException(\"Job method is 'async void'; change the return type to Task.\");","typeGuard":"public static bool IsAsyncTaskMethod(MethodInfo m)\n    => m != null && (m.ReturnType == typeof(Task) || m.ReturnType.IsGenericType && m.ReturnType.GetGenericTypeDefinition() == typeof(Task<>));","tryCatchPattern":"try { BackgroundJob.Enqueue<T>(x => x.Work()); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"Async void\")) { /* change 'async void' to 'async Task' */ }","preventionTips":["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."],"tags":["not-supported","async","job-definition","task"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}