pardeike/Harmony · error · ArgumentException
No field found at given index in class
Error message
No field found at given index in class {originalType?.AssemblyQualifiedName ?? "null"} What it means
When binding an injected patch parameter whose name uses the instance-field-by-index convention (`__N` derived from INSTANCE_FIELD_PREFIX), Harmony resolves the Nth declared field of the patched type via AccessTools.DeclaredField. If no declared field exists at that index (type has fewer fields, or ordering changed), this ArgumentException is thrown with the field's argument name.
Solutions
- Reduce the index or verify the target type's declared field count/order at runtime (e.g. via AccessTools.GetDeclaredFields(originalType)).
- Prefer referencing the field by name instead of index to be resilient to reordering.
- Pin the target assembly version or add a startup check that the expected field exists before applying the patch.
Example fix
// before
static void Postfix(MyClass __this, int __5) { ... }
// after
static void Postfix(MyClass __this, int ___myFieldName) { ... } Defensive patterns
Strategy: validation
Validate before calling
var fields = AccessTools.GetDeclaredFields(targetType);
if (index < 0 || index >= fields.Count)
throw new InvalidOperationException($"{targetType} has no declared field at index {index}"); Type guard
bool HasFieldAtIndex(Type t, int i) => AccessTools.DeclaredField(t, i) is not null;
Try / catch
try { harmony.PatchAll(); }
catch (ArgumentException ex) when (ex.Message.Contains("No field found at given index")) { log.Error(ex); } Prevention
- Reference fields by name, not index, for version resilience
- Re-verify field order after every target update
- Gate patches on a target-version check
When it happens
Trigger: Naming a patch parameter with the instance-field numeric prefix (e.g. `__0`, `__2`) in a patch for a type that has no declared field at that index; the target type changed between versions so field order/count no longer matches.
Common situations: Target assembly updated and fields reordered/removed; patch written against a different class than intended; using the index form on a struct/class where all fields are inherited rather than declared.
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 such field defined 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/8e886b1e79a2ce04.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Internal/MethodCreatorTools.cs:291
if (injectionType == InjectionType.ArgsArray)
{
if (config.localVariables.TryGetValue(InjectionType.ArgsArray, out var argsArrayVar))
codes.Add(Ldloc[argsArrayVar]);
else
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;
}
View on GitHub (pinned to e7872dc170)