pardeike/Harmony · error · ArgumentException

FieldRefAccess< > for , caused an exception

Error message

FieldRefAccess<{typeof(F)}> for {type}, {fieldName} caused an exception

What it means

Wrapping ArgumentException from FieldRefAccess<F>(typeColonName / type, fieldName): thrown when any step fails — field lookup returning null, the struct-instance-field check, or delegate creation. InnerException carries the root cause; the message names the type and field for quick identification.

Solutions

  1. Inspect ex.InnerException for the actual failure
  2. Validate with AccessTools.Field(type, fieldName) before building the delegate
  3. Confirm the field is static or declared on a class
  4. Log/echo the exact typeColonName string to catch format or rename issues

Example fix

// before
var acc = AccessTools.FieldRefAccess<int>("Game.Enemy:healt"); // typo
// after
var acc = AccessTools.FieldRefAccess<int>("Game.Enemy:health");
Defensive patterns

Strategy: try-catch

Validate before calling

var fi = AccessTools.Field(type, fieldName);
if (fi is null) throw new InvalidOperationException($"Field {fieldName} not found on {type}");
if (fi.IsStatic is false && fi.DeclaringType is Type dt && dt.IsValueType) throw new InvalidOperationException("Struct instance field");

Try / catch

try { var acc = AccessTools.FieldRefAccess<F>(typeColonName); }
catch (ArgumentException ex) { /* inspect ex.InnerException */ }

Prevention

When it happens

Trigger: Calling AccessTools.FieldRefAccess<F>("Namespace.Type:fieldName") or FieldRefAccess<F>(type, fieldName) where the field does not exist, is an instance field of a struct, or cannot support a ref-returning delegate.

Common situations: Typo in TypeFullName:MemberName string after an assembly update; attempting struct instance field refs; obfuscated field names in shipped game assemblies.

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/d2d0ecacde049ddf. Report an issue: GitHub.

Appendix: source

Thrown at Harmony/Tools/AccessTools.cs:1381

			try
			{
				var fieldInfo = Field(type, fieldName);
				if (fieldInfo is null)
					throw new MissingFieldException(type.Name, fieldName);
				// Backwards compatibility: This supports static fields, even those defined in structs. For static fields, T is effectively ignored.
				if (fieldInfo.IsStatic is false && fieldInfo.DeclaringType is Type declaringType)
				{
					// When fieldInfo is passed to FieldRefAccess methods, the T generic class constraint is insufficient to ensure that
					// the field is not a struct instance field, since T could be object, ValueType, or an interface that the struct implements.
					if (declaringType.IsValueType)
						throw new ArgumentException("Either FieldDeclaringType must be a class or field must be static");
				}
				// Field's declaring type cannot be object, since object has no fields, so always need a castclass for T=object.
				return Tools.FieldRefAccess<object, F>(fieldInfo, needCastclass: true);
			}
			catch (Exception ex)
			{
				throw new ArgumentException($"FieldRefAccess<{typeof(F)}> for {type}, {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"> type of the field</typeparam>
		/// <param name="typeColonName">The member in the form <c>TypeFullName:MemberName</c>, where TypeFullName matches the form recognized by <a href="https://docs.microsoft.com/en-us/dotnet/api/system.type.gettype">Type.GetType</a> like <c>Some.Namespace.Type</c>.</param>
		/// <returns>A readable/assignable <see cref="FieldRef{T,F}"/> delegate with <c>T=object</c></returns>
		///
		public static FieldRef<object, F> FieldRefAccess<F>(string typeColonName)
		{
			var info = Tools.TypColonName(typeColonName);
			return FieldRefAccess<F>(info.type, info.name);
		}

		/// <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="T">
		/// An arbitrary type if the field is static; otherwise the class that defines the field, or a parent class (including <see cref="object"/>),
		/// implemented interface, or derived class of this type ("<c>instanceOfT is FieldDeclaringType</c>" must be possible)

View on GitHub (pinned to e7872dc170)