pardeike/Harmony · error · Exception

Wrong type of for method . Expected , got

Error message

Wrong type of {InjectedParameter.RESULT_REF_VAR} for method {original.FullDescription()}. Expected {expectedTypeRef.FullName}, got {resultType.FullName}

What it means

The original method returns by ref and ResultRef injection applies, but the injected parameter's type is not exactly `RefResult<T>` (by ref) where T is the target's ref element type. Harmony computes the expected type and throws this Exception when the declared parameter type differs, because the emitted IL (Ldloca of the RefResult local) requires an exact match.

Solutions

  1. Declare the parameter as `ref RefResult<T>` where T exactly equals the target's ref element type (returnType.GetElementType()).
  2. Log the expected type from the exception message and align your patch signature with it.
  3. Add a runtime assertion comparing your parameter type to typeof(RefResult<>).MakeGenericType(target.ReturnType.GetElementType()).MakeByRefType() before patching.

Example fix

// before (target returns ref long)
static void Postfix(RefResult<int> result) { ... }

// after
static void Postfix(ref RefResult<long> result) { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

var expected = typeof(RefResult<>).MakeGenericType(original.ReturnType.GetElementType()).MakeByRefType();
if (resultRefParam.ParameterType != expected)
    throw new InvalidOperationException($"ResultRef param must be {expected}");

Type guard

bool ResultRefTypeMatches(MethodInfo original, ParameterInfo p) =>
    original.ReturnType.IsByRef &&
    p.ParameterType == typeof(RefResult<>).MakeGenericType(original.ReturnType.GetElementType()).MakeByRefType();

Try / catch

try { harmony.Patch(original, postfix: new HarmonyMethod(fix)); }
catch (Exception ex) when (ex.Message.Contains("Wrong type of")) { log.Error(ex); }

Prevention

When it happens

Trigger: Declaring a ResultRef parameter as RefResult<WrongT>, as a non-generic type, by value instead of by ref, or as a custom wrapper type - while patching a `ref T` method.

Common situations: Target's ref element type changed (ref int -> ref long); writing RefResult<T> without the `ref`/by-ref requirement; patch shared across methods returning different element types.

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


AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15). Data as JSON: /api/errors/a9504eda8e492d99. Report an issue: GitHub.

Appendix: source

Thrown at Harmony/Internal/MethodCreatorTools.cs:357

							codes.Add(Box[returnType]);
							tmpObjectVar = config.DeclareLocal(typeof(object));
							codes.Add(Stloc[tmpObjectVar]);
							codes.Add(Ldloca[tmpObjectVar]);
						}
					}
					continue;
				}

				if (injectionType == InjectionType.ResultRef)
				{
					if (!returnType.IsByRef)
						throw new Exception(
							 $"Cannot use {InjectionType.ResultRef} with non-ref return type {returnType.FullName} of method {original.FullDescription()}");

					var resultType = paramType;
					var expectedTypeRef = typeof(RefResult<>).MakeGenericType(returnType.GetElementType()).MakeByRefType();
					if (resultType != expectedTypeRef)
						throw new Exception(
							 $"Wrong type of {InjectedParameter.RESULT_REF_VAR} for method {original.FullDescription()}. Expected {expectedTypeRef.FullName}, got {resultType.FullName}");

					codes.Add(Ldloca[config.GetLocal(InjectionType.ResultRef)]);

					refResultUsed = true;
					continue;
				}

				if (injection.argumentMode != ArgumentMode.Original && config.localVariables.TryGetValue(paramRealName, out var localBuilder))
				{
					var ldlocCode = paramType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;
					codes.Add(new CodeInstruction(ldlocCode, localBuilder));
					continue;
				}

				int argumentIdx;
				if (injection.argumentMode == ArgumentMode.Original)
				{

View on GitHub (pinned to e7872dc170)