pardeike/Harmony · error · Exception

Cannot get result from void method

Error message

Cannot get result from void method {original.FullDescription()}

What it means

A patch parameter requests the original method's return value (InjectionType.Result, via the RESULT_VAR naming convention such as a `result`/`__result`-style injected parameter). Harmony throws because the original method returns void, so there is no result value to inject. Use the annotation only on methods with a non-void return type.

Solutions

  1. Remove the result parameter from the patch signature since the target returns void.
  2. Use a state/local injection or an instance-field/argument injection instead to observe data from a void method.
  3. Split the patch class so void targets use a separate patch method without a result parameter.

Example fix

// before (target: void Save())
static void Postfix([HarmonyArgument("result")] object result) { ... }

// after
static void Postfix() { ... }
Defensive patterns

Strategy: validation

Validate before calling

if (original.ReturnType == typeof(void) && patchUsesResultInjection(patch))
    throw new InvalidOperationException("Target is void; remove the result parameter");

Type guard

bool ResultUsable(MethodInfo original) => original.ReturnType != typeof(void);

Try / catch

try { harmony.Patch(original, postfix: new HarmonyMethod(fix)); }
catch (Exception ex) when (ex.Message.Contains("Cannot get result from void method")) { log.Error(ex); }

Prevention

When it happens

Trigger: Annotating/declaring a patch parameter as the result injection (InjectionType.Result) on a patch whose original method has return type void - e.g. patching a `void Process()` method while declaring a result parameter in the patch signature.

Common situations: Reusing a generic patch class across methods where some targets are void; refactoring the target method to void while keeping the old patch signature; copy-pasting a postfix between void and non-void targets.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at Harmony/Internal/MethodCreatorTools.cs:323

						codes.Add(paramType.IsByRef ? Ldflda[fieldInfo] : Ldfld[fieldInfo]);
					}
					continue;
				}

				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]);

View on GitHub (pinned to e7872dc170)