pardeike/Harmony · error · ArgumentException

No such field defined in class

Error message

No such field defined in class {originalType?.AssemblyQualifiedName ?? "null"}

What it means

When a patch parameter name references an instance field by name (the declared-field prefix convention), Harmony looks it up with AccessTools.Field on the patched type. If no field with that name is declared on the type, this ArgumentException is thrown. It means the patch's parameter name does not correspond to any field of the target class.

Solutions

  1. Fix the parameter name to exactly match a declared field of the target type (check AccessTools.Field(originalType, name)).
  2. If the field lives in a base class, patch or reference accordingly / use the accessor that resolves inherited fields.
  3. Add a pre-patch validation step that asserts the field exists before applying patches.

Example fix

// before
static void Postfix(Player __instance, int ___healthPoints) { ... }

// after (actual field name is 'hp')
static void Postfix(Player __instance, int ___hp) { ... }
Defensive patterns

Strategy: validation

Validate before calling

if (AccessTools.Field(targetType, fieldName) is null)
    throw new InvalidOperationException($"Field '{fieldName}' missing on {targetType}");

Type guard

bool HasField(Type t, string name) => AccessTools.Field(t, name) is not null;

Try / catch

try { harmony.PatchAll(); }
catch (ArgumentException ex) when (ex.Message.Contains("No such field defined in class")) { log.Error(ex); }

Prevention

When it happens

Trigger: Declaring a patch parameter with the field prefix (e.g. `___someField`) where `someField` is not a field (declared) on the original type - typo, renamed field, field moved to a base class, or patching the wrong type.

Common situations: Game/app update renamed or moved the field; field is defined in a base type while the convention expects it declared on the patched type; case-sensitivity typos (`___HP` vs `___hp`).

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at Harmony/Internal/MethodCreatorTools.cs:297

						codes.Add(Ldnull);
					continue;
				}

				if (injection.argumentMode != ArgumentMode.Original && paramRealName.StartsWith(INSTANCE_FIELD_PREFIX, StringComparison.Ordinal))
				{
					var fieldName = paramRealName.Substring(INSTANCE_FIELD_PREFIX.Length);
					FieldInfo fieldInfo;
					if (fieldName.All(char.IsDigit))
					{
						fieldInfo = AccessTools.DeclaredField(originalType, int.Parse(fieldName));
						if (fieldInfo is null)
							throw new ArgumentException($"No field found at given index in class {originalType?.AssemblyQualifiedName ?? "null"}", fieldName);
					}
					else
					{
						fieldInfo = AccessTools.Field(originalType, fieldName);
						if (fieldInfo is null)
							throw new ArgumentException($"No such field defined in class {originalType?.AssemblyQualifiedName ?? "null"}", fieldName);
					}

					if (fieldInfo.IsStatic)
						codes.Add(paramType.IsByRef ? Ldsflda[fieldInfo] : Ldsfld[fieldInfo]);
					else
					{
						codes.Add(Ldarg_0);
						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

View on GitHub (pinned to e7872dc170)