pardeike/Harmony · error · AmbiguousMatchException
Ambiguous match in Harmony patch for
Error message
Ambiguous match in Harmony patch for {type}:{name} What it means
AccessTools.Method rethrows AmbiguousMatchException when Type.GetMethod finds several methods with the same name. Harmony first tries a fallback lookup via FindIncludingBaseTypes; if that also cannot resolve a unique match, it throws this message with the original exception as InnerException. It signals that the name alone is not enough to identify the patch target.
Solutions
- Pass parameter types: AccessTools.Method(typeof(T), "Process", new[] { typeof(string) })
- Or pass an expression: AccessTools.Method((Action<T, string>)instance.Process) to pin the exact overload
- List candidates with AccessTools.GetDeclaredMethods(typeof(T)).Where(m => m.Name == "Process") and pick by signature
Example fix
// before
var m = AccessTools.Method(typeof(Foo), "Process");
// after
var m = AccessTools.Method(typeof(Foo), "Process", new[] { typeof(string), typeof(int) }); Defensive patterns
Strategy: validation
Validate before calling
var candidates = typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Where(m => m.Name == name).ToList();
if (candidates.Count > 1 && parameters is null) throw new InvalidOperationException("Overloads found: pass parameters"); Prevention
- Always disambiguate with a parameters array when a method has overloads
- Use expression-based overloads (AccessTools.Method(() => instance.M())) for compile-time safety
- Pin target assembly versions; overloads appear across game/framework updates
When it happens
Trigger: AccessTools.Method(typeof(T), "MethodName") where the type (including base types) has multiple methods named MethodName and no `parameters` argument was given to disambiguate; also hit by patch helpers like EnumeratorMoveNext, Finalizer lookups, and m_PrepForRemoting resolution that go through AccessTools.Method.
Common situations: Patching overloaded methods such as `Process(string)` vs `Process(object)`, interface + class implementations, or a method overloaded in a base and derived type; very common in Unity/game modding where framework types have many overloads.
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
- The type must declare an empty constructor (the constructor…
- Value cannot be null. (Parameter 'fromMethod')
- Value cannot be null. (Parameter 'method')
- Value cannot be null. (Parameter 'config.original')
- Ambiguous match for HarmonyMethod
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/fd49c9fc201ca914.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/AccessTools.cs:707
if (string.IsNullOrEmpty(name))
{
FileLog.Debug("AccessTools.Method: name is null/empty");
return null;
}
MethodInfo result;
var modifiers = new ParameterModifier[] { };
if (parameters is null)
{
try
{
result = FindIncludingBaseTypes(type, t => t.GetMethod(name, all));
}
catch (AmbiguousMatchException ex)
{
result = FindIncludingBaseTypes(type, t => t.GetMethod(name, all, null, [], modifiers));
if (result is null)
{
throw new AmbiguousMatchException($"Ambiguous match in Harmony patch for {type}:{name}", ex);
}
}
}
else
{
result = FindIncludingBaseTypes(type, t => t.GetMethod(name, all, null, parameters, modifiers));
}
if (result is null)
{
FileLog.Debug($"AccessTools.Method: Could not find method for type {type} and name {name} and parameters {parameters?.Description()}");
return null;
}
if (generics is not null)
result = result.MakeGenericMethod(generics);
return result;
}
View on GitHub (pinned to e7872dc170)