HangfireIO/Hangfire · error · InvalidOperationException

The type `{type.FullName}` does not contain a method with si

Error message

The type `{type.FullName}` does not contain a method with signature `{key.MethodName}({parametersString})`

What it means

InvalidOperationException thrown inside InvocationData's method-deserializer cache when TypeResolver resolved the type but GetNonOpenMatchingMethod found no method with the stored MethodName and parameter type names. The message prints the expected signature so you can compare it against the current code. Once thrown, the cache entry is not stored, so the resolution is retried on the next attempt.

Source

Thrown at src/Hangfire.Core/Storage/InvocationData.cs:350

            Func<string, Type> typeResolver, string typeName, string methodName, string parameterTypes,
            out Type type, out MethodInfo methodInfo)
        {
            var entry = MethodDeserializerCache.GetOrAdd(
                new MethodDeserializerCacheKey { TypeResolver = typeResolver, TypeName = typeName, MethodName = methodName, ParameterTypes = parameterTypes },
                static key =>
                {
                    var type = key.TypeResolver(key.TypeName);
                    var parameterTypesArray = DeserializeParameterTypesArray(TypeHelper.CurrentTypeSerializer, key.ParameterTypes);
                    var parameterTypes = parameterTypesArray?.Select(key.TypeResolver).ToArray();
                    var method = type.GetNonOpenMatchingMethod(key.MethodName, parameterTypes);

                    if (method == null)
                    {
                        var parametersString = parameterTypes != null
                            ? String.Join(", ", parameterTypes.Select(static x => x.Name))
                            : key.ParameterTypes ?? String.Empty;
                    
                        throw new InvalidOperationException(
                            $"The type `{type.FullName}` does not contain a method with signature `{key.MethodName}({parametersString})`");
                    }

                    return new MethodDeserializerCacheValue { Type = type, Method = method };
                });

            type = entry.Type;
            methodInfo = entry.Method;
        }

        private static object DeserializeArgument(string argument, Type type)
        {
            object value;
            try
            {
                value = SerializationHelper.Deserialize(argument, type, SerializationOption.User);
            }
            catch (Exception jsonException) when (jsonException.IsCatchableExceptionType())

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Read the printed signature from the message and add/restore a method on the resolved type that matches MethodName(parameterTypes) exactly.
  2. Delete the stale job from storage if it can no longer be executed.
  3. Ensure the enqueuing and executing processes reference the same assembly version and method signatures.
  4. Avoid renaming job methods; if you must, ship a forwarding stub during the transition.

Example fix

// before: stored signature ProcessOrder(int) but code now takes Guid
public void ProcessOrder(Guid id) { ... }

// after
public void ProcessOrder(Guid id) { ... }
public void ProcessOrder(int legacyId) => ProcessOrder(Lookup(legacyId));
Defensive patterns

Strategy: try-catch

Validate before calling

static bool MethodSignatureExists(Type type, string methodName, Type[] parameterTypes)
    => type.GetMethod(methodName, parameterTypes) != null;

Try / catch

try
{
    invocationData.Deserialize();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("does not contain a method"))
{
    logger.Warn("Stale job references missing method; deleting. Detail: {Msg}", ex.Message);
    storage.Delete(jobId);
}

Prevention

When it happens

Trigger: A persisted job references a method name + parameter types that no longer exist on the resolved type: method renamed, parameter type renamed, method removed, or overload mismatch (e.g. stored parameter is an interface but the method now takes a concrete type).

Common situations: Refactoring job methods without deleting queued jobs; changing a parameter from one type to another; splitting a class so the method moved types; version skew between the enqueuing app and the worker app.

Related errors


AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13). Data as JSON: /api/errors/cc3015d68eaa2fa1. Report an issue: GitHub.