pardeike/Harmony · error · ArgumentException
You can only patch implemented methods/constructors. Patch…
Error message
You can only patch implemented methods/constructors. Patch the declared method {declaredMember.FullDescription()} instead. What it means
Harmony can only patch the method that actually declares a body. If the MethodInfo passed to Patch() is an abstract method, interface method, or otherwise non-implemented member, Harmony resolves the declaring definition and throws an ArgumentException telling you to patch that declared method instead.
Solutions
- Patch the concrete implemented method: look the method up on the concrete type that provides the body
- Use Harmony's GetDeclaredMember() result from the error message as the patch target
- If the target is abstract/interface-only, patch a concrete derived implementation or use a different hook point
Example fix
// before
var original = typeof(IPlayer).GetMethod("Update");
harmony.Patch(original, prefix: prefixMethod);
// after
var original = typeof(Player).GetMethod("Update"); // concrete implementing type
harmony.Patch(original, prefix: prefixMethod); Defensive patterns
Strategy: validation
Validate before calling
if (original is not null && !original.IsDeclaredMember())
{
var declared = original.GetDeclaredMember();
original = declared as MethodInfo ?? throw new InvalidOperationException($"Patch the declared method {declared.FullDescription()} instead");
} Try / catch
try { harmony.Patch(original, prefix: prefix); }
catch (ArgumentException ex) when (ex.Message.Contains("implemented methods/constructors")) { /* retarget to concrete type */ } Prevention
- Look patch targets up on concrete implementing types, not interfaces or abstract bases
- Avoid patching methods obtained through generic interface dispatch
- Check original.IsAbstract / !original.HasMethodBody() before patching
When it happens
Trigger: Calling Patch() with a MethodInfo obtained from a derived type, a base-type reference, a MakeGenericMethod result, or an interface method where IsDeclaredMember() is false — e.g. patching typeof(IFoo).GetMethod("Bar") or patching an abstract base method.
Common situations: Developers patch methods accessed through interface types or generic base classes; patching virtual methods via a base-class MethodInfo obtained from an interface lookup; targets refactored from concrete to abstract in a library update.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Method has wrong return type (should be assignable to )
- Null method for
- Null method for
- Multiple possible indexers were found.
- Field must not be static
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/7fa2a28432236f22.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Public/PatchProcessor.cs:177
{
lock (locker)
{
return HarmonySharedState.GetPatchedMethods();
}
}
/// <summary>Applies all registered patches</summary>
/// <returns>The generated replacement method</returns>
///
public MethodInfo Patch()
{
if (original is null)
throw new NullReferenceException($"Null method for {instance.Id}");
if (original.IsDeclaredMember() is false)
{
var declaredMember = original.GetDeclaredMember();
throw new ArgumentException($"You can only patch implemented methods/constructors. Patch the declared method {declaredMember.FullDescription()} instead.");
}
lock (locker)
{
var patchInfo = HarmonySharedState.GetPatchInfo(original) ?? new PatchInfo();
patchInfo.AddPrefixes(instance.Id, prefix);
patchInfo.AddPostfixes(instance.Id, postfix);
patchInfo.AddTranspilers(instance.Id, transpiler);
patchInfo.AddFinalizers(instance.Id, finalizer);
patchInfo.AddInnerPrefixes(instance.Id, innerprefix);
patchInfo.AddInnerPostfixes(instance.Id, innerpostfix);
var replacement = PatchFunctions.UpdateWrapper(original, patchInfo);
HarmonySharedState.UpdatePatchInfo(original, replacement, patchInfo);
return replacement;
}
}
View on GitHub (pinned to e7872dc170)