pardeike/Harmony · error · Exception
Cannot assign method return type
Error message
Cannot assign method return type {returnType.FullName} to {InjectedParameter.RESULT_VAR} type {resultType.FullName} for method {original.FullDescription()} What it means
The patch requests the original's return value (InjectionType.Result), but the declared type of the injected parameter is not assignable from the original method's return type. Harmony validates `resultType.IsAssignableFrom(returnType)` before emitting the load of the result local and throws when types are incompatible, preventing invalid IL.
Solutions
- Change the injected result parameter's type to exactly the original method's return type (or a compatible base/interface).
- Use `object` and box manually if you need a generic patch, respecting value-type handling.
- Verify original.FullDescription() return type at patch-application time and pick/branch to the right patch method.
Example fix
// before (target returns int)
static void Postfix([HarmonyArgument("result")] string result) { ... }
// after
static void Postfix([HarmonyArgument("result")] int result) { ... } Defensive patterns
Strategy: type-guard
Validate before calling
var paramType = resultParam.ParameterType;
if (!paramType.IsAssignableFrom(original.ReturnType))
throw new InvalidOperationException($"Result param {paramType} cannot accept {original.ReturnType}"); Type guard
bool ResultTypeMatches(MethodInfo original, ParameterInfo p) =>
p.ParameterType.IsAssignableFrom(original.ReturnType); Try / catch
try { harmony.Patch(original, postfix: new HarmonyMethod(fix)); }
catch (Exception ex) when (ex.Message.Contains("Cannot assign method return type")) { log.Error(ex); } Prevention
- Type the result parameter exactly as the target's return type
- Re-check signatures when target return types change
- Test patches against the exact target assembly version
When it happens
Trigger: Declaring a result-injected parameter of a type that the original's return type cannot be assigned to, e.g. `string` result parameter on a method returning `int`, or an unboxed value-type parameter for a boxed/object return.
Common situations: Target method return type changed between versions (int -> long, T -> object); patch shared across overloads with different return types; using `ref`/`out` parameter forms that don't match the result type rules.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Wrong type of for method . Expected , got
- __state type mismatch in patch
- Prefix patch has not "bool" or "void" return type
- Return type of pass through postfix
- Postfix patch must have a "void" return type
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/ab7cda22a3167e52.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Internal/MethodCreatorTools.cs:328
if (injectionType == InjectionType.State)
{
var ldlocCode = paramType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;
if (config.localVariables.TryGetValue(patch.DeclaringType?.AssemblyQualifiedName ?? "null", out var stateVar))
codes.Add(new CodeInstruction(ldlocCode, stateVar));
else
codes.Add(Ldnull);
continue;
}
if (injectionType == InjectionType.Result)
{
if (returnType == typeof(void))
throw new Exception($"Cannot get result from void method {original.FullDescription()}");
var resultType = paramType;
if (resultType.IsByRef && returnType.IsByRef is false)
resultType = resultType.GetElementType();
if (resultType.IsAssignableFrom(returnType) is false)
throw new Exception($"Cannot assign method return type {returnType.FullName} to {InjectedParameter.RESULT_VAR} type {resultType.FullName} for method {original.FullDescription()}");
var ldlocCode = paramType.IsByRef && returnType.IsByRef is false ? OpCodes.Ldloca : OpCodes.Ldloc;
if (returnType.IsValueType && paramType == typeof(object).MakeByRefType())
ldlocCode = OpCodes.Ldloc;
codes.Add(new CodeInstruction(ldlocCode, config.GetLocal(InjectionType.Result)));
if (returnType.IsValueType)
{
if (paramType == typeof(object))
codes.Add(Box[returnType]);
else if (paramType == typeof(object).MakeByRefType())
{
codes.Add(Box[returnType]);
tmpObjectVar = config.DeclareLocal(typeof(object));
codes.Add(Stloc[tmpObjectVar]);
codes.Add(Ldloca[tmpObjectVar]);
}
}
continue;
}
View on GitHub (pinned to e7872dc170)