pardeike/Harmony · error · ArgumentException

StaticFieldRefAccess<

Error message

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

What it means

AccessTools.StaticFieldRefAccess<F>(type, fieldName) wraps any failure while resolving or accessing the named static field in an ArgumentException, preserving the original exception as InnerException. Harmony throws it because the requested static field could not be resolved (MissingFieldException) or its ref-returning accessor could not be invoked.

Solutions

  1. Check the inner exception (ex.InnerException) to see whether it is MissingFieldException (name/type wrong) or something else.
  2. Verify the field exists and is static: AccessTools.Field(type, fieldName) != null and fieldInfo.IsStatic.
  3. Ensure the generic type F exactly matches the field's declared type.
  4. Use AccessTools.StaticFieldRefAccess<T, F>("FieldName") with the correct declaring type T.

Example fix

// before
var refAccess = AccessTools.StaticFieldRefAccess<int>(typeof(GameState), "sccore");
// after
var refAccess = AccessTools.StaticFieldRefAccess<int>(typeof(GameState), "score");
Defensive patterns

Strategy: try-catch

Validate before calling

var fi = AccessTools.Field(type, fieldName);
if (fi is null || !fi.IsStatic || fi.FieldType != typeof(F))
    throw new InvalidOperationException($"{type.Name}.{fieldName} is not a static {typeof(F)} field");

Type guard

bool IsValidStaticField<F>(Type type, string name) => AccessTools.Field(type, name) is { IsStatic: true } fi && fi.FieldType == typeof(F);

Try / catch

try { var r = AccessTools.StaticFieldRefAccess<F>(type, fieldName); }
catch (ArgumentException ex) when (ex.InnerException is MissingFieldException) { /* wrong type/name */ }
catch (ArgumentException ex) { /* type mismatch - log ex.InnerException */ }

Prevention

When it happens

Trigger: Calling AccessTools.StaticFieldRefAccess<F>(type, fieldName) where type has no field named fieldName (inner MissingFieldException), or Tools.StaticFieldRefAccess<F>(fieldInfo)() fails when invoking the generated accessor, e.g. the field type does not match F.

Common situations: Typo in the field name, field renamed in a game/library update, wrong type parameter F vs the actual static field type, or targeting a field that is instance instead of static.

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

Appendix: source

Thrown at Harmony/Tools/AccessTools.cs:1682

		/// 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 (can be class or struct) the field is defined in</param>
		/// <param name="fieldName">The name of the field</param>
		/// <returns>A readable/assignable reference to the field</returns>
		///
		public static ref F StaticFieldRefAccess<F>(Type type, string fieldName)
		{
			try
			{
				var fieldInfo = Field(type, fieldName);
				if (fieldInfo is null)
					throw new MissingFieldException(type.Name, fieldName);
				return ref Tools.StaticFieldRefAccess<F>(fieldInfo)();
			}
			catch (Exception ex)
			{
				throw new ArgumentException($"StaticFieldRefAccess<{typeof(F)}> for {type}, {fieldName} caused an exception", ex);
			}
		}

		/// <summary>Creates a static field reference</summary>
		/// <typeparam name="F">The 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 reference to the field</returns>
		///
		public static ref F StaticFieldRefAccess<F>(string typeColonName)
		{
			var info = Tools.TypColonName(typeColonName);
			return ref StaticFieldRefAccess<F>(info.type, info.name);
		}

		/// <summary>Creates a static field reference</summary>
		/// <typeparam name="T">An arbitrary type (by convention, the type the field is defined in)</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),

View on GitHub (pinned to e7872dc170)