pardeike/Harmony · error · ArgumentException
FieldRefAccess< , > for , caused an exception
Error message
FieldRefAccess<{typeof(T)}, {typeof(F)}> for {instance}, {fieldName} caused an exception What it means
Wrapping ArgumentException thrown by FieldRefAccess<T,F>(fieldName) when any inner operation fails (value-type T, field not found, type mismatch, delegate creation failure). The original exception is the InnerException and the message includes the instance and field name for diagnosis.
Solutions
- Check ex.InnerException for the root cause
- Confirm the field exists with the exact type: AccessTools.Field(typeof(T), fieldName)?.FieldType == typeof(F)
- Ensure T is a reference type; use StaticFieldRefAccess for static fields
Example fix
// before
var acc = AccessTools.FieldRefAccess<Player, float>("hp"); // hp is actually int
// after
var acc = AccessTools.FieldRefAccess<Player, int>("hp"); Defensive patterns
Strategy: try-catch
Validate before calling
if (typeof(T).IsValueType) throw new InvalidOperationException("T must be a class");
var fi = AccessTools.Field(typeof(T), fieldName);
if (fi?.FieldType != typeof(F)) throw new InvalidOperationException("Field missing or type mismatch"); Try / catch
try { var acc = AccessTools.FieldRefAccess<T, F>(fieldName); }
catch (ArgumentException ex) { /* inspect ex.InnerException */ } Prevention
- Validate the FieldInfo before creating the delegate
- Keep field names in one constants class to survive renames
- Test ref-delegate creation at patch initialization, not lazily
When it happens
Trigger: Calling AccessTools.FieldRefAccess<T, F>(fieldName) with T a struct, a fieldName that does not resolve to an instance field of type F, or when delegate construction throws.
Common situations: Field renamed in a target-assembly update; F declared as int while field is float; struct instance type used by mistake.
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
- FieldRefAccess< > for , caused an exception
- T (FieldRefAccess instance type) must not be a value type
- Either FieldDeclaringType must be a class or field must be…
- FieldRefAccess< , > for caused an exception
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/3fcc9ade70a731eb.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/AccessTools.cs:1328
/// </para>
/// </remarks>
///
public static ref F FieldRefAccess<T, F>(T instance, string fieldName)
{
if (instance is null)
throw new ArgumentNullException(nameof(instance));
if (fieldName is null)
throw new ArgumentNullException(nameof(fieldName));
try
{
var delegateInstanceType = typeof(T);
if (delegateInstanceType.IsValueType)
throw new ArgumentException("T (FieldRefAccess instance type) must not be a value type");
return ref Tools.FieldRefAccess<T, F>(Tools.GetInstanceField(delegateInstanceType, fieldName), needCastclass: false)(instance);
}
catch (Exception ex)
{
throw new ArgumentException($"FieldRefAccess<{typeof(T)}, {typeof(F)}> for {instance}, {fieldName} caused an exception", ex);
}
}
/// <summary>Creates a field reference delegate for an instance field of a class or static field (NOT an instance field of a struct)</summary>
/// <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="type">
/// The type that defines the field, or derived class of this type; must not be a struct type unless the field is static
/// </param>
/// <param name="fieldName">The name of the field</param>
/// <returns>
/// A readable/assignable <see cref="FieldRef{T,F}"/> delegate with <c>T=object</c>
/// (for static fields, the <c>instance</c> delegate parameter is ignored)
/// </returns>
/// <remarks>
View on GitHub (pinned to e7872dc170)