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

  1. Check ex.InnerException for the root cause
  2. Confirm the field exists with the exact type: AccessTools.Field(typeof(T), fieldName)?.FieldType == typeof(F)
  3. 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

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


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)