{"record":{"id":"ae09505c884dbf1c","repo":"HangfireIO/Hangfire","slug":"job-method-can-not-contain-unassigned-generic-type","errorCode":null,"errorMessage":"Job method can not contain unassigned generic type parameters.","messagePattern":"Job method can not contain unassigned generic type parameters\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Common/Job.cs","lineNumber":482,"sourceCode":"\n        private static void Validate(\n            Type type, \n            [InvokerParameterName] string typeParameterName,\n            MethodInfo method, \n            // ReSharper disable once UnusedParameter.Local\n            [InvokerParameterName] string methodParameterName,\n            // ReSharper disable once UnusedParameter.Local\n            int argumentCount,\n            [InvokerParameterName] string argumentParameterName)\n        {\n            if (!method.IsPublic)\n            {\n                throw new NotSupportedException(\"Only public methods can be invoked in the background. Ensure your method has the `public` access modifier, and you aren't using explicit interface implementation.\");\n            }\n\n            if (method.ContainsGenericParameters)\n            {\n                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.\");","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Common/Job.cs#L464-L500","documentation":"NotSupportedException thrown by Job.Validate when method.ContainsGenericParameters is true — i.e., the method has open (unassigned) generic type parameters. Because jobs are serialized and invoked in a possibly different process by name and serialized arguments, the runtime cannot reconstruct a closed generic method from an unassigned type parameter. The check fires when a generic method is enqueued without the type arguments being inferable/assigned at definition time.","triggerScenarios":"Enqueuing () => service.GenericMethod<T>() where T is not bound; a method declared as void Run<T>(T arg) enqueued without a concrete T; reflection-supplied MethodInfo that still has ContainsGenericParameters == true.","commonSituations":"Building a generic job method and forgetting to close it; enqueuing via a MethodInfo obtained from reflection on an open generic method definition; dynamic dispatch scenarios where the type argument is not pinned.","solutions":["Make the method non-generic by fixing the argument type, or close the generic at call site: BackgroundJob.Enqueue(() => service.GenericMethod<int>(42)).","If using a MethodInfo directly, call method.MakeGenericMethod(typeof(int)) to produce a closed method before constructing the Job.","Wrap the generic method in a non-generic public method that internally calls the generic one."],"exampleFix":"// before — open generic parameter\npublic class Worker {\n    public void Run<T>(T arg) { ... }\n}\nBackgroundJob.Enqueue(() => worker.Run(someValue)); // T unbound at def site\n\n// after — concrete method or closed generic\npublic class Worker {\n    public void RunInt(int arg) { ... }\n}\nBackgroundJob.Enqueue<Worker>(x => x.RunInt(42));","handlingStrategy":"validation","validationCode":"if (method.ContainsGenericParameters)\n    throw new NotSupportedException(\"Job method has open generic parameters; close them before creating the job.\");\nvar closed = method.IsGenericMethodDefinition ? method.MakeGenericMethod(typeof(int)) : method;","typeGuard":"public static bool IsClosedGenericMethod(MethodInfo m)\n    => m != null && !m.ContainsGenericParameters;","tryCatchPattern":"try { BackgroundJob.Enqueue(() => svc.Run<T>(arg)); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"generic type parameters\")) { /* close the generic or wrap in a non-generic method */ }","preventionTips":["Avoid open generic job methods; close them at the call site or wrap in a non-generic method.","When using reflection to build a Job, call MakeGenericMethod before constructing the Job.","Audit job methods for generic parameters during code review."],"tags":["not-supported","job-definition","generics","reflection"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}