pardeike/Harmony · error · ArgumentException
Field must not be static
Error message
Field must not be static
What it means
Harmony's Tools.GetInstanceField resolves a field by name and refuses to return static fields because the caller asked for an instance field via reflection on a specific instance type. Static fields live on the type, not the instance, so returning one here would be a caller bug or a wrong fieldName/type pair.
Solutions
- Make the field non-static in the target type if an instance field is genuinely intended
- Use a static-field accessor (e.g. AccessTools.Field + fieldInfo.GetValue(null), or a static field ref helper) instead of GetInstanceField
- Verify the field's modifiers with AccessTools.DeclaredField/fieldInfo.IsStatic before calling
Example fix
// before
var fi = Tools.GetInstanceField(typeof(Player), "instanceCount"); // instanceCount is static
// after
var fi = typeof(Player).GetField("instanceCount", BindingFlags.Static | BindingFlags.NonPublic); Defensive patterns
Strategy: validation
Validate before calling
var fi = AccessTools.Field(type, fieldName);
if (fi == null) throw new MissingFieldException(type.Name, fieldName);
if (fi.IsStatic) throw new ArgumentException($"{type.Name}.{fieldName} is static; use a static field accessor"); Type guard
bool IsInstanceField(Type t, string name) =>
t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) is { IsStatic: false }; Try / catch
try { var fi = Tools.GetInstanceField(type, fieldName); }
catch (ArgumentException ex) when (ex.Message == "Field must not be static") { /* fall back to static access */ }
catch (MissingFieldException) { /* field doesn't exist */ } Prevention
- Check fieldInfo.IsStatic before using instance-field helpers
- Keep target-field lookups in one place so refactors in the patched library surface once
- Prefer AccessTools helpers and verify with FieldExists
When it happens
Trigger: Calling Tools.GetInstanceField(type, fieldName) (directly or via AccessTools/field-ref helpers) where fieldName names a static field on the given type instead of an instance field.
Common situations: Target class refactored an instance field into a static one; copy-pasting a field name without checking its modifiers; using the helper to fetch constants or cached/singleton fields that are static.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Method has wrong return type (should be assignable to )
- Null method for
- You can only patch implemented methods/constructors. Patch…
- Null method for
- Multiple possible indexers were found.
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/c30fd0fb183ab685.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/Tools.cs:123
ValidateFieldType<F>(fieldInfo);
var dm = new DynamicMethodDefinition($"__refget_{fieldInfo.DeclaringType?.Name ?? "null"}_static_fi_{fieldInfo.Name}",
typeof(F).MakeByRefType(), []);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldsflda, fieldInfo);
il.Emit(OpCodes.Ret);
return dm.Generate().CreateDelegate<FieldRef<F>>();
}
internal static FieldInfo GetInstanceField(Type type, string fieldName)
{
var fieldInfo = Field(type, fieldName);
if (fieldInfo is null)
throw new MissingFieldException(type.Name, fieldName);
if (fieldInfo.IsStatic)
throw new ArgumentException("Field must not be static");
return fieldInfo;
}
internal static bool FieldRefNeedsClasscast(Type delegateInstanceType, Type declaringType)
{
var needCastclass = false;
if (delegateInstanceType != declaringType)
{
needCastclass = delegateInstanceType.IsAssignableFrom(declaringType);
if (needCastclass is false && declaringType.IsAssignableFrom(delegateInstanceType) is false)
throw new ArgumentException("FieldDeclaringType must be assignable from or to T (FieldRefAccess instance type) - " +
"\"instanceOfT is FieldDeclaringType\" must be possible");
}
return needCastclass;
}
internal static void ValidateStructField<T, F>(FieldInfo fieldInfo) where T : struct
{
View on GitHub (pinned to e7872dc170)