pardeike/Harmony · error · HarmonyException

Ambiguous match for HarmonyMethod

Error message

Ambiguous match for HarmonyMethod[{attr.Description()}]

What it means

Harmony's GetOriginalMethod resolves the original method from a HarmonyMethod attribute, e.g. for patching operators like op_Addition. When AccessTools.DeclaredMethod finds multiple overloads matching the name (and optionally argument types), .NET throws AmbiguousMatchException, which Harmony wraps in this HarmonyException so the attribute description is included.

Solutions

  1. Set attr.argumentTypes to the exact parameter types of the overload you want to patch
  2. If patching an operator, verify the operator does not have multiple implementations (e.g. lhs/rhs vs lifted nullable forms); pick argumentTypes accordingly
  3. Catch HarmonyException and inspect the inner AmbiguousMatchException plus the attribute Description() to see which method name/type was ambiguous
  4. Patch the specific overload via a HarmonyMethod constructed from a MethodInfo instead of by name

Example fix

// before
[HarmonyPatch(typeof(Vector3), MethodType.Normal, nameof(Vector3.Add))]
// after
[HarmonyPatch(typeof(Vector3), nameof(Vector3.Add), new[] { typeof(Vector3) })]
Defensive patterns

Strategy: validation

Validate before calling

var mi = AccessTools.DeclaredMethod(attr.declaringType, "op_" + attr.methodType.ToString().Replace("Operator", ""), attr.argumentTypes);
if (mi is null) throw new InvalidOperationException($"No unique method for {attr.Description()}; specify argumentTypes");

Type guard

bool IsResolvable(HarmonyMethod attr) => AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes) is not null;

Try / catch

try { PatchOriginalMethod(attr); } catch (HarmonyException ex) when (ex.InnerException is AmbiguousMatchException) { log.Error($"Ambiguous patch target: {ex.Message}", ex); }

Prevention

When it happens

Trigger: Patching a type that declares an overloaded method via attr.methodType (e.g. methodType derived from a name like 'Add') or an operator/overload where attr.argumentTypes is null or not specific enough, so more than one declared method matches the resolved name.

Common situations: Patching operator overloads (e.g. op_Addition with multiple implicit-conversion-compatible operand combinations), patching overloaded methods by name without specifying argumentTypes, and switching .NET versions where an extra overload was added to a base class library type.

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/6bb138c799a0bcf4. Report an issue: GitHub.

Appendix: source

Thrown at Harmony/Internal/PatchTools.cs:203

					case MethodType.OperatorBitwiseAnd:
					case MethodType.OperatorBitwiseOr:
					case MethodType.OperatorExclusiveOr:
					case MethodType.OperatorLeftShift:
					case MethodType.OperatorRightShift:
					case MethodType.OperatorEquality:
					case MethodType.OperatorInequality:
					case MethodType.OperatorGreaterThan:
					case MethodType.OperatorLessThan:
					case MethodType.OperatorGreaterThanOrEqual:
					case MethodType.OperatorLessThanOrEqual:
					case MethodType.OperatorComma:
						var methodName = "op_" + attr.methodType.ToString().Replace("Operator", "");
						return AccessTools.DeclaredMethod(attr.declaringType, methodName, attr.argumentTypes);
				}
			}
			catch (AmbiguousMatchException ex)
			{
				throw new HarmonyException($"Ambiguous match for HarmonyMethod[{attr.Description()}]", ex.InnerException ?? ex);
			}

			return null;
		}
	}
}

View on GitHub (pinned to e7872dc170)