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
- Check the inner exception (ex.InnerException) to see whether it is MissingFieldException (name/type wrong) or something else.
- Verify the field exists and is static: AccessTools.Field(type, fieldName) != null and fieldInfo.IsStatic.
- Ensure the generic type F exactly matches the field's declared type.
- 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
- Always pre-resolve with AccessTools.Field and null-check before taking ref access.
- Assert fieldInfo.IsStatic and FieldType == typeof(F).
- Pin/re-verify member names after every target library update.
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
- Field must not be static
- StaticFieldRefAccess<
- StaticFieldRefAccess<
- The type must declare an empty constructor (the constructor…
- Value cannot be null. (Parameter 'fromMethod')
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)