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

  1. Verify the field name with AccessTools.Field(typeof(T), fieldName) before calling
  2. Check the target assembly version for renamed fields and update the name
  3. Confirm typeof(F) equals fieldInfo.FieldType
  4. 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

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


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&lt;T, F&gt;(ref instance, fieldName)</c> is functionally equivalent to <c>StructFieldRefAccess&lt;T, F&gt;(fieldName)(ref instance)</c>.

View on GitHub (pinned to e7872dc170)