pardeike/Harmony · error · ArgumentException
StructFieldRefAccess<
Error message
StructFieldRefAccess<{typeof(T)}, {typeof(F)}> for {fieldName} caused an exception What it means
Catch-all wrapper in AccessTools.StructFieldRefAccess<T,F>(fieldName): any exception while resolving the instance field via Tools.GetInstanceField(typeof(T), fieldName) or building the struct ref delegate is rethrown as an ArgumentException naming T, F and fieldName, with the cause as InnerException.
Solutions
- Verify the field name with AccessTools.Field(typeof(T), fieldName) before calling
- Check the target assembly version for renamed fields and update the name
- Confirm typeof(F) equals fieldInfo.FieldType
- Inspect InnerException to identify whether it was lookup failure vs delegate failure
Example fix
// before
var rf = AccessTools.StructFieldRefAccess<MyStruct, int>("_count"); // field renamed
// after
var fi = AccessTools.Field(typeof(MyStruct), "_count") ?? throw new MissingFieldException(nameof(MyStruct), "_count");
var rf = AccessTools.StructFieldRefAccess<MyStruct, int>(fi); Defensive patterns
Strategy: validation
Validate before calling
if (AccessTools.Field(typeof(T), fieldName) is null) throw new MissingFieldException(typeof(T).Name, fieldName);
Try / catch
try { var rf = AccessTools.StructFieldRefAccess<T, F>(fieldName); }
catch (ArgumentException ex) { throw new InvalidOperationException($"Field '{fieldName}' missing or invalid on {typeof(T)}", ex.InnerException ?? ex); } Prevention
- Resolve and check the FieldInfo before using string-based overloads
- Track field names of patched assemblies in tests that run against the real target version
- Prefer FieldInfo-based overloads for early, clearer failures
When it happens
Trigger: fieldName does not exist on struct T (typically throws NullReferenceException/ArgumentNullException from GetInstanceField), or the field type does not match F.
Common situations: Typo'd field name; target library renamed a private field; the field moved to a base class or became auto-property backing field with compiler-generated naming.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- StructFieldRefAccess<
- StructFieldRefAccess<
- StructFieldRefAccess<
- T (FieldRefAccess instance type) must not be a value type
- FieldRefAccess< , > for caused an exception
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/1fd96a046c4b4e7d.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/AccessTools.cs:1539
/// <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="fieldName">The name of the field</param>
/// <returns>A readable/assignable <see cref="StructFieldRef{T,F}"/> delegate</returns>
///
public static StructFieldRef<T, F> StructFieldRefAccess<T, F>(string fieldName) where T : struct
{
if (fieldName is null)
throw new ArgumentNullException(nameof(fieldName));
try
{
return Tools.StructFieldRefAccess<T, F>(Tools.GetInstanceField(typeof(T), fieldName));
}
catch (Exception ex)
{
throw new ArgumentException($"StructFieldRefAccess<{typeof(T)}, {typeof(F)}> for {fieldName} caused an exception", ex);
}
}
/// <summary>Creates an instance field reference for a specific instance 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">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="StructFieldRefAccess{T, F}(string)"/> instead.
/// <c>StructFieldRefAccess<T, F>(ref instance, fieldName)</c> is functionally equivalent to <c>StructFieldRefAccess<T, F>(fieldName)(ref instance)</c>.
View on GitHub (pinned to e7872dc170)