{"record":{"id":"90dbc9a0c4b4237b","repo":"pardeike/Harmony","slug":"cannot-use-injectiontype-resultref-with-non-ref-return-type","errorCode":null,"errorMessage":"Cannot use {InjectionType.ResultRef} with non-ref return type {returnType.FullName} of method {original.FullDescription()}","messagePattern":"Cannot use (.+?) with non-ref return type (.+?) of method (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Harmony/Internal/MethodCreatorTools.cs","lineNumber":351,"sourceCode":"\t\t\t\t\tif (returnType.IsValueType)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif (paramType == typeof(object))\r\n\t\t\t\t\t\t\tcodes.Add(Box[returnType]);\r\n\t\t\t\t\t\telse if (paramType == typeof(object).MakeByRefType())\r\n\t\t\t\t\t\t{\r\n\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","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Internal/MethodCreatorTools.cs#L333-L369","documentation":"A patch parameter requests a reference to the original method's return value (InjectionType.ResultRef, backed by RefResult<T>). Harmony only supports this when the original method returns by ref (`ref T`); otherwise there is no ref location to hand out, so it throws listing the actual return type.","triggerScenarios":"Declaring a ResultRef-injected parameter (RefResult<T>) in a patch targeting a method whose return type is not IsByRef - i.e. any normal by-value return, including `void` and plain `T`.","commonSituations":"Applying a ref-returning patch to a non-ref overload of the same method name; library update removed `ref` from the target's signature while the patch still assumes it.","solutions":["Use a normal result injection (InjectionType.Result) instead of ResultRef for by-value returns.","If you need to mutate the result, use a `ref T` parameter pass-through postfix rather than ResultRef.","Confirm the target signature actually returns `ref T` (check MethodInfo.ReturnType.IsByRef) before registering the patch."],"exampleFix":"// before (target returns int, not ref int)\nstatic void Postfix([HarmonyArgument(\"resultref\")] RefResult<int> resultRef) { ... }\n\n// after\nstatic void Postfix(ref int result) { ... }","handlingStrategy":"validation","validationCode":"if (usesResultRef && !original.ReturnType.IsByRef)\n    throw new InvalidOperationException(\"ResultRef requires a ref-returning method\");","typeGuard":"bool SupportsResultRef(MethodInfo original) => original.ReturnType.IsByRef;","tryCatchPattern":"try { harmony.Patch(original, postfix: new HarmonyMethod(fix)); }\ncatch (Exception ex) when (ex.Message.Contains(\"with non-ref return type\")) { log.Error(ex); }","preventionTips":["Only use ResultRef for `ref T` methods","Fall back to Result injection for by-value returns","Inspect target signature with ildasm/decompiler before patching"],"tags":["harmony","ref-return","injection","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}