{"record":{"id":"5e2976f11efb5570","repo":"HangfireIO/Hangfire","slug":"the-type-method-declaringtype-must-be-derived","errorCode":null,"errorMessage":"The type `{method.DeclaringType}` must be derived from the `{type}` type.","messagePattern":"The type `(.+?)` must be derived from the `(.+?)` type\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Common/Job.cs","lineNumber":492,"sourceCode":"        {\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.\");\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            }","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Common/Job.cs#L474-L510","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before — type/method mismatch\nvar method = typeof(EmailService).GetMethod(\"Send\");\nvar job = new Job(typeof(ReportService), method, args);\n\n// after — type matches the method's declaring type\nvar job = new Job(typeof(EmailService), method, args);\n// or infer from expression\nvar job = Job.FromExpression<EmailService>(x => x.Send());","handlingStrategy":"validation","validationCode":"if (!method.DeclaringType.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))\n    throw new ArgumentException($\"Type {type} does not declare or inherit method {method.Name} (declared on {method.DeclaringType}).\");","typeGuard":"public static bool TypeMatchesMethod(Type type, MethodInfo method)\n    => method?.DeclaringType != null && method.DeclaringType.GetTypeInfo().IsAssignableFrom(type?.GetTypeInfo());","tryCatchPattern":"try { var job = new Job(type, method, args); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"must be derived from\")) { /* align type with method.DeclaringType */ }","preventionTips":["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."],"tags":["argument","job-definition","type-mismatch","reflection"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}