HangfireIO/Hangfire · error · ArgumentException
The type `{method.DeclaringType}` must be derived from the `
Error message
The type `{method.DeclaringType}` must be derived from the `{type}` type. What it means
ArgumentException thrown by Job.Validate when the method's DeclaringType is not assignable to the specified job Type. Hangfire allows passing an explicit type (e.g., an interface) with a method declared on a different type, but requires method.DeclaringType.IsAssignableFrom(type) — i.e., the job type must be the same as or derive from/implement the method's declaring type. This catches mismatches where a method and type are unrelated, which would cause invocation-time InvalidCastExceptions or missing-method errors in the performer.
Source
Thrown at src/Hangfire.Core/Common/Job.cs:492
{
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.");
}
var parameters = method.GetParameters();
if (parameters.Length != argumentCount)
{
throw new ArgumentException(
"Argument count must be equal to method parameter count.",
argumentParameterName);
}View on GitHub (pinned to c236dd0f93)
Solutions
- Ensure the Type passed to the Job constructor (or TType) is the method's DeclaringType or a type that inherits/implements it.
- When using reflection, derive the type from method.DeclaringType rather than hard-coding.
- Use the FromExpression overloads which infer the type automatically from the expression.
Example fix
// before — type/method mismatch
var method = typeof(EmailService).GetMethod("Send");
var job = new Job(typeof(ReportService), method, args);
// after — type matches the method's declaring type
var job = new Job(typeof(EmailService), method, args);
// or infer from expression
var job = Job.FromExpression<EmailService>(x => x.Send()); Defensive patterns
Strategy: validation
Validate before calling
if (!method.DeclaringType.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
throw new ArgumentException($"Type {type} does not declare or inherit method {method.Name} (declared on {method.DeclaringType})."); Type guard
public static bool TypeMatchesMethod(Type type, MethodInfo method)
=> method?.DeclaringType != null && method.DeclaringType.GetTypeInfo().IsAssignableFrom(type?.GetTypeInfo()); Try / catch
try { var job = new Job(type, method, args); }
catch (ArgumentException ex) when (ex.Message.Contains("must be derived from")) { /* align type with method.DeclaringType */ } Prevention
- Derive the Job type from method.DeclaringType rather than hard-coding an unrelated type.
- Prefer Job.FromExpression<TType>(x => x.Method()) which infers the type correctly.
- When refactoring a method to a new class, update all Job construction sites.
When it happens
Trigger: Constructing new Job(typeof(Foo), typeof(Bar).GetMethod("Run")) where Bar does not declare or inherit Run; passing a MethodInfo from an unrelated class; enqueuing via the typed overload with a TType that does not declare the method.
Common situations: Copy-paste errors when building Job from reflection; refactoring a method to a different class without updating the type argument; using a MethodInfo from a base class but passing a derived type that does not actually inherit it (e.g., shadowing).
Related errors
- Argument count must be equal to method parameter count.
- Expression body should be of type `MethodCallExpression`
- 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.
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/5e2976f11efb5570.
Report an issue: GitHub.