pardeike/Harmony · error · ArgumentException
FieldRefAccess< , > for caused an exception
Error message
FieldRefAccess<{typeof(T)}, {typeof(F)}> for {fieldName} caused an exception What it means
This is the wrapping ArgumentException thrown by FieldRefAccess<T,F> when ANY exception occurs inside the method — including the value-type check, field resolution (GetInstanceField), or delegate construction. The original exception is preserved as InnerException. It gives context about which type/field combination failed.
Solutions
- Inspect the InnerException to see the real cause and fix accordingly
- Verify the field exists and its type matches F: AccessTools.Field(typeof(T), fieldName)?.FieldType
- Ensure T is a class, not a value type; use StaticFieldRefAccess for static fields
- Enable Harmony FileLog debug to see which lookup step failed
Example fix
// before
var acc = AccessTools.FieldRefAccess<Player, int>("hp"); // inner: field renamed to health
// after
var acc = AccessTools.FieldRefAccess<Player, int>("health"); Defensive patterns
Strategy: try-catch
Validate before calling
var fi = AccessTools.Field(typeof(T), fieldName);
if (fi is null || fi.FieldType != typeof(F)) throw new InvalidOperationException("Field missing or type mismatch"); Try / catch
try { var acc = AccessTools.FieldRefAccess<T, F>(type, fieldName); }
catch (ArgumentException ex) { /* inspect ex.InnerException */ } Prevention
- Always check InnerException — it holds the real cause
- Confirm field name against the actual target assembly version
- Match F exactly to fi.FieldType
- Catch ArgumentException at patch-creation time, not at runtime patch application
When it happens
Trigger: Calling AccessTools.FieldRefAccess<T, F>(type, fieldName) where the inner step fails: T is a value type, the field does not exist, the field type is not F, or the field is inaccessible for ref-returning delegate creation.
Common situations: Renamed/obfuscated field names in a game update, field type changed from int to long (F no longer matches), or T bound to a struct.
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/630cad9a5ca3c59d.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/AccessTools.cs:1287
/// For backwards compatibility, there is no class constraint on <typeparamref name="T"/>.
/// Instead, the non-value-type check is done at runtime within the method.
/// </para>
/// </remarks>
///
public static FieldRef<T, F> FieldRefAccess<T, F>(string fieldName)
{
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 Tools.FieldRefAccess<T, F>(Tools.GetInstanceField(delegateInstanceType, fieldName), needCastclass: false);
}
catch (Exception ex)
{
throw new ArgumentException($"FieldRefAccess<{typeof(T)}, {typeof(F)}> for {fieldName} caused an exception", ex);
}
}
/// <summary>Creates an instance field reference for a specific instance of a class</summary>
/// <typeparam name="T">The class that defines the instance field, or derived class of this type</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">The instance</param>
/// <param name="fieldName">The name of the field</param>
/// <returns>A readable/assignable reference to the field</returns>
/// <remarks>
/// <para>
/// This method is meant for one-off access to a field's value for a single instance.
/// If you need to access a field's value for potentially multiple instances, use <see cref="FieldRefAccess{T, F}(string)"/> instead.
/// <c>FieldRefAccess<T, F>(instance, fieldName)</c> is functionally equivalent to <c>FieldRefAccess<T, F>(fieldName)(instance)</c>.
View on GitHub (pinned to e7872dc170)