pardeike/Harmony · error · ArgumentException

Using requires an additional attribute for specifying the…

Error message

Using {PatchTools.harmonyPatchAllFullName} requires an additional attribute for specifying the Class/Type

What it means

[HarmonyPatchAll] tells Harmony to patch many methods at once, but it does not say on which class those methods live. When the patch class does not also declare a declaring type (via [HarmonyPatch(typeof(...))] on the class or Harmony.CreateAndPatchAll(type, type)), GetBulkMethods throws.

Solutions

  1. Add a class-level attribute specifying the target type: [HarmonyPatch(typeof(TargetClass))] alongside [HarmonyPatchAll]
  2. Or call Harmony.CreateAndPatchAll(typeof(YourPatchClass), "id") so the declaring type is explicit
  3. Or drop [HarmonyPatchAll] and specify each target with per-method attributes

Example fix

// before
[HarmonyPatchAll]
class Patches { static void Postfix() { } }
// after
[HarmonyPatchAll]
[HarmonyPatch(typeof(TargetClass))]
class Patches { static void Postfix() { } }
Defensive patterns

Strategy: validation

Validate before calling

if (type.GetCustomAttributes(true).Any(a => a.GetType().FullName == PatchTools.harmonyPatchAllFullName)
    && !type.GetCustomAttributes(true).Any(a => a is HarmonyAttribute && ((HarmonyAttribute)a).info.declaringType != null))
    throw new Exception("HarmonyPatchAll needs a class-level HarmonyPatch(typeof(...))");

Prevention

When it happens

Trigger: Calling PatchAll on a class marked only with [HarmonyPatchAll] without any [HarmonyPatch(typeof(X))] class-level attribute, or Harmony.PatchAll() where the container type has no declaring type attribute.

Common situations: Copy-pasting a [HarmonyPatchAll] class and dropping the class-level [HarmonyPatch(typeof(...))] line; writing patch classes with only method-level attributes plus HarmonyPatchAll.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at Harmony/Public/PatchClassProcessor.cs:251

				job.postfixes.Do(patch => patchInfo.RemovePatch(patch.method));
				job.prefixes.Do(patch => patchInfo.RemovePatch(patch.method));
			}
			job.transpilers.Do(patch => patchInfo.RemovePatch(patch.method));
			if (hasBody)
				job.finalizers.Do(patch => patchInfo.RemovePatch(patch.method));

			var replacement = PatchFunctions.UpdateWrapper(job.original, patchInfo);
			HarmonySharedState.UpdatePatchInfo(job.original, replacement, patchInfo);
		}

		List<MethodBase> GetBulkMethods()
		{
			var isPatchAll = containerType.GetCustomAttributes(true).Any(a => a.GetType().FullName == PatchTools.harmonyPatchAllFullName);
			if (isPatchAll)
			{
				var type = containerAttributes.declaringType;
				if (type is null)
					throw new ArgumentException($"Using {PatchTools.harmonyPatchAllFullName} requires an additional attribute for specifying the Class/Type");

				var list = new List<MethodBase>();
				list.AddRange(AccessTools.GetDeclaredConstructors(type).Cast<MethodBase>());
				list.AddRange(AccessTools.GetDeclaredMethods(type).Cast<MethodBase>());
				var props = AccessTools.GetDeclaredProperties(type);
				list.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method is not null).Cast<MethodBase>());
				list.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method is not null).Cast<MethodBase>());
				return list;
			}

			var result = new List<MethodBase>();

			var targetMethods = RunMethod<HarmonyTargetMethods, IEnumerable<MethodBase>>(null, null);
			if (targetMethods is object)
			{
				string error = null;
				result = [.. targetMethods];
				if (result is null)

View on GitHub (pinned to e7872dc170)