pardeike/Harmony · error · ArgumentException
StructFieldRefAccess<
Error message
StructFieldRefAccess<{typeof(T)}, {typeof(F)}> for {instance}, {fieldName} caused an exception What it means
Catch-all wrapper in the instance-specific StructFieldRefAccess<T,F>(ref instance, fieldName): any failure resolving the field or creating the ref delegate is rethrown as an ArgumentException naming T, F, the instance and fieldName, with the cause as InnerException.
Solutions
- Validate the field exists via AccessTools.Field(typeof(T), fieldName) first
- Inspect ex.InnerException for the underlying failure
- Match F exactly to the field's FieldType
- Switch to the FieldInfo-based overload to fail at lookup time instead of inside the wrapper
Example fix
// before ref var v = ref AccessTools.StructFieldRefAccess<MyStruct, int>(ref instance, "_count"); // after var fi = AccessTools.Field(typeof(MyStruct), "_count"); if (fi is null) return; ref var v = ref AccessTools.StructFieldRefAccess<MyStruct, int>(fi)(ref instance);
Defensive patterns
Strategy: validation
Validate before calling
var fi = AccessTools.Field(typeof(T), fieldName); if (fi is null || fi.FieldType != typeof(F)) throw new MissingFieldException(typeof(T).Name, fieldName);
Try / catch
try { ref var v = ref AccessTools.StructFieldRefAccess<T, F>(ref instance, fieldName); }
catch (ArgumentException ex) { Log.Error(ex.InnerException ?? ex, "StructFieldRefAccess failed for {Field}", fieldName); } Prevention
- Match F exactly to the field type
- Use FieldInfo lookups once at startup, fail fast there
- Re-verify field names after every target-library update
When it happens
Trigger: Same lookup failures as error 86 (missing field name, wrong F) occurring in the overload that takes the struct instance by ref.
Common situations: Struct field renamed in an updated dependency; calling with a struct type that does not actually declare the field; mismatched generic F.
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/16fcf0ddf65a713a.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/AccessTools.cs:1571
/// <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>.
/// </para>
/// </remarks>
///
public static ref F StructFieldRefAccess<T, F>(ref T instance, string fieldName) where T : struct
{
if (fieldName is null)
throw new ArgumentNullException(nameof(fieldName));
try
{
return ref Tools.StructFieldRefAccess<T, F>(Tools.GetInstanceField(typeof(T), fieldName))(ref instance);
}
catch (Exception ex)
{
throw new ArgumentException($"StructFieldRefAccess<{typeof(T)}, {typeof(F)}> for {instance}, {fieldName} caused an exception", ex);
}
}
/// <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">
/// 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="fieldInfo">The field</param>
/// <returns>A readable/assignable <see cref="StructFieldRef{T,F}"/> delegate</returns>
/// <remarks>
/// <para>
/// This method is meant for cases where the field has already been obtained, avoiding the field searching cost in
/// e.g. <see cref="StructFieldRefAccess{T, F}(string)"/>.
/// </para>
/// </remarks>
View on GitHub (pinned to e7872dc170)