HangfireIO/Hangfire · error · NotSupportedException
Job method can not contain unassigned generic type parameter
Error message
Job method can not contain unassigned generic type parameters.
What it means
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.
Source
Thrown at src/Hangfire.Core/Common/Job.cs:482
private static void Validate(
Type type,
[InvokerParameterName] string typeParameterName,
MethodInfo method,
// ReSharper disable once UnusedParameter.Local
[InvokerParameterName] string methodParameterName,
// ReSharper disable once UnusedParameter.Local
int argumentCount,
[InvokerParameterName] string argumentParameterName)
{
if (!method.IsPublic)
{
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.");
}
if (method.ContainsGenericParameters)
{
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.");View on GitHub (pinned to c236dd0f93)
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.
Example fix
// before — open generic parameter
public class Worker {
public void Run<T>(T arg) { ... }
}
BackgroundJob.Enqueue(() => worker.Run(someValue)); // T unbound at def site
// after — concrete method or closed generic
public class Worker {
public void RunInt(int arg) { ... }
}
BackgroundJob.Enqueue<Worker>(x => x.RunInt(42)); Defensive patterns
Strategy: validation
Validate before calling
if (method.ContainsGenericParameters)
throw new NotSupportedException("Job method has open generic parameters; close them before creating the job.");
var closed = method.IsGenericMethodDefinition ? method.MakeGenericMethod(typeof(int)) : method; Type guard
public static bool IsClosedGenericMethod(MethodInfo m)
=> m != null && !m.ContainsGenericParameters; Try / catch
try { BackgroundJob.Enqueue(() => svc.Run<T>(arg)); }
catch (NotSupportedException ex) when (ex.Message.Contains("generic type parameters")) { /* close the generic or wrap in a non-generic method */ } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Only public methods can be invoked in the background. Ensure
- Global methods are not supported. Use class methods instead.
- The type `{method.DeclaringType}` must be derived from the `
- Async void methods are not supported. Use async Task instead
- Argument count must be equal to method parameter count.
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/ae09505c884dbf1c.
Report an issue: GitHub.