{"record":{"id":"a9504eda8e492d99","repo":"pardeike/Harmony","slug":"wrong-type-of-injectedparameter-result-ref-var-for-method","errorCode":null,"errorMessage":"Wrong type of {InjectedParameter.RESULT_REF_VAR} for method {original.FullDescription()}. Expected {expectedTypeRef.FullName}, got {resultType.FullName}","messagePattern":"Wrong type of (.+?) for method (.+?)\\. Expected (.+?), got (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Harmony/Internal/MethodCreatorTools.cs","lineNumber":357,"sourceCode":"\t\t\t\t\t\t\tcodes.Add(Box[returnType]);\r\n\t\t\t\t\t\t\ttmpObjectVar = config.DeclareLocal(typeof(object));\r\n\t\t\t\t\t\t\tcodes.Add(Stloc[tmpObjectVar]);\r\n\t\t\t\t\t\t\tcodes.Add(Ldloca[tmpObjectVar]);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (injectionType == InjectionType.ResultRef)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!returnType.IsByRef)\r\n\t\t\t\t\t\tthrow new Exception(\r\n\t\t\t\t\t\t\t $\"Cannot use {InjectionType.ResultRef} with non-ref return type {returnType.FullName} of method {original.FullDescription()}\");\r\n\r\n\t\t\t\t\tvar resultType = paramType;\r\n\t\t\t\t\tvar expectedTypeRef = typeof(RefResult<>).MakeGenericType(returnType.GetElementType()).MakeByRefType();\r\n\t\t\t\t\tif (resultType != expectedTypeRef)\r\n\t\t\t\t\t\tthrow new Exception(\r\n\t\t\t\t\t\t\t $\"Wrong type of {InjectedParameter.RESULT_REF_VAR} for method {original.FullDescription()}. Expected {expectedTypeRef.FullName}, got {resultType.FullName}\");\r\n\r\n\t\t\t\t\tcodes.Add(Ldloca[config.GetLocal(InjectionType.ResultRef)]);\r\n\r\n\t\t\t\t\trefResultUsed = true;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (injection.argumentMode != ArgumentMode.Original && config.localVariables.TryGetValue(paramRealName, out var localBuilder))\r\n\t\t\t\t{\r\n\t\t\t\t\tvar ldlocCode = paramType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;\r\n\t\t\t\t\tcodes.Add(new CodeInstruction(ldlocCode, localBuilder));\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tint argumentIdx;\r\n\t\t\t\tif (injection.argumentMode == ArgumentMode.Original)\r\n\t\t\t\t{\r","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Internal/MethodCreatorTools.cs#L339-L375","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Declare the parameter as `ref RefResult<T>` where T exactly equals the target's ref element type (returnType.GetElementType()).","Log the expected type from the exception message and align your patch signature with it.","Add a runtime assertion comparing your parameter type to typeof(RefResult<>).MakeGenericType(target.ReturnType.GetElementType()).MakeByRefType() before patching."],"exampleFix":"// before (target returns ref long)\nstatic void Postfix(RefResult<int> result) { ... }\n\n// after\nstatic void Postfix(ref RefResult<long> result) { ... }","handlingStrategy":"type-guard","validationCode":"var expected = typeof(RefResult<>).MakeGenericType(original.ReturnType.GetElementType()).MakeByRefType();\nif (resultRefParam.ParameterType != expected)\n    throw new InvalidOperationException($\"ResultRef param must be {expected}\");","typeGuard":"bool ResultRefTypeMatches(MethodInfo original, ParameterInfo p) =>\n    original.ReturnType.IsByRef &&\n    p.ParameterType == typeof(RefResult<>).MakeGenericType(original.ReturnType.GetElementType()).MakeByRefType();","tryCatchPattern":"try { harmony.Patch(original, postfix: new HarmonyMethod(fix)); }\ncatch (Exception ex) when (ex.Message.Contains(\"Wrong type of\")) { log.Error(ex); }","preventionTips":["Always declare `ref RefResult<T>` with T = target's ref element type","Regenerate patch signatures when target element types change","Add a signature unit test per ref-returning target"],"tags":["harmony","ref-return","type-mismatch","injection"],"backgroundTag":"type-mismatch","analyzedSha":"e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c","analyzedAt":"2026-09-15T22:47:11.550Z","contentChangedAt":"2026-09-15T22:47:11.550Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}