pardeike/Harmony · error · ArgumentException
FieldRefAccess< , > for , caused an exception
Error message
FieldRefAccess<{typeof(T)}, {typeof(F)}> for {instance}, {fieldInfo} caused an exception What it means
Catch-all wrapper in the instance-taking AccessTools.FieldRefAccess<T,F>(fieldInfo, instance): any failure while creating or invoking the ref delegate is rethrown as an ArgumentException naming T, F, the instance and the FieldInfo, with the real exception as InnerException.
Solutions
- Log and inspect ex.InnerException for the root cause
- Ensure instance is a live (non-null) object of type T or derived
- Confirm fieldInfo is a non-static instance field on a class
- Pre-validate T/fieldInfo/instance before calling (IsValueType, IsStatic, DeclaringType checks)
Example fix
// before
var rf = AccessTools.FieldRefAccess<T, F>(fi);
ref var v = ref rf(instance);
// after
if (fi.DeclaringType is { IsValueType: true }) throw new NotSupportedException("use StructFieldRefAccess");
var rf = AccessTools.FieldRefAccess<T, F>(fi);
ref var v = ref rf(instance ?? throw new InvalidOperationException("instance is null")); Defensive patterns
Strategy: try-catch
Validate before calling
if (instance is null) throw new ArgumentNullException(nameof(instance));
if (typeof(T).IsValueType || fieldInfo is { IsStatic: true } || fieldInfo.DeclaringType is { IsValueType: true }) throw new ArgumentException("invalid FieldRefAccess parameters"); Type guard
static bool IsValidClassFieldRef<T, F>(FieldInfo fi) => !typeof(T).IsValueType && fi is { IsStatic: false } && fi.DeclaringType is { IsValueType: false }; Try / catch
try { var rf = AccessTools.FieldRefAccess<T, F>(fi); return rf(instance); }
catch (ArgumentException ex) { throw new InvalidOperationException("FieldRefAccess failed", ex.InnerException ?? ex); } Prevention
- Ensure the instance is non-null and exactly type T or derived
- Cache delegates per (T, fieldInfo) pair, never across types
- Validate all three inputs (T, fieldInfo, instance) before building refs
When it happens
Trigger: Any of: T is a value type, field is static, field's declaring type is a struct, or the returned delegate fails when invoked with an incompatible/null instance.
Common situations: Passing a null or wrong-typed instance to the returned delegate; patch setup errors during startup where the inner exception is the actual diagnosis.
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
- FieldRefAccess< , > for caused an exception
- T (FieldRefAccess instance type) must not be a value type
- FieldRefAccess< , > for caused an exception
- FieldRefAccess< , > for , caused an exception
- Either FieldDeclaringType must be a class or field must be…
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/4a94349679ab713c.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/AccessTools.cs:1503
var delegateInstanceType = typeof(T);
if (delegateInstanceType.IsValueType)
throw new ArgumentException("T (FieldRefAccess instance type) must not be a value type");
if (fieldInfo.IsStatic)
throw new ArgumentException("Field must not be static");
var needCastclass = false;
if (fieldInfo.DeclaringType is Type declaringType)
{
// When fieldInfo is passed to FieldRefAccess methods, the T generic class constraint is insufficient to ensure that
// the field is not a struct instance field, since T could be object, ValueType, or an interface that the struct implements.
if (declaringType.IsValueType)
throw new ArgumentException("FieldDeclaringType must be a class");
needCastclass = Tools.FieldRefNeedsClasscast(delegateInstanceType, declaringType);
}
return ref Tools.FieldRefAccess<T, F>(fieldInfo, needCastclass)(instance);
}
catch (Exception ex)
{
throw new ArgumentException($"FieldRefAccess<{typeof(T)}, {typeof(F)}> for {instance}, {fieldInfo} caused an exception", ex);
}
}
/// <summary>A readable/assignable reference delegate to an instance field of a struct</summary>
/// <typeparam name="T">The struct that defines the instance field</typeparam>
/// <typeparam name="F">
/// The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
/// a type that <see cref="Type.IsAssignableFrom(Type)">is assignable from</see> that type; or if the field's type is an enum type,
/// either that type or the underlying integral type of that enum type
/// </typeparam>
/// <param name="instance">A reference to the runtime instance to access the field</param>
/// <returns>A readable/assignable reference to the field</returns>
///
public delegate ref F StructFieldRef<T, F>(ref T instance) where T : struct;
/// <summary>Creates a field reference delegate for an instance field of a struct</summary>
/// <typeparam name="T">The struct that defines the instance field</typeparam>
/// <typeparam name="F">
View on GitHub (pinned to e7872dc170)