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
- Fix the parameter name to exactly match a declared field of the target type (check AccessTools.Field(originalType, name)).
- If the field lives in a base class, patch or reference accordingly / use the accessor that resolves inherited fields.
- 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
- Copy field names directly from decompiled target code
- Add a preflight scan of all ___field parameters at startup
- Handle target renames behind an accessor helper
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
- No field found at given index in class
- Cannot get result from void method
- Parameter " " not found in method
- Parameter does not contain a valid index
- The type must declare an empty constructor (the constructor…
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)