pardeike/Harmony · error · ArgumentException
StaticFieldRefAccess<
Error message
StaticFieldRefAccess<{typeof(T)}, {typeof(F)}> for {fieldInfo} caused an exception What it means
AccessTools.StaticFieldRefAccess<T, F>(fieldInfo) wraps any exception from Tools.StaticFieldRefAccess<F>(fieldInfo)() in an ArgumentException with the FieldInfo in the message. It indicates the given static FieldInfo could not be turned into or invoked as a typed ref accessor for field type F.
Solutions
- Inspect InnerException for the root cause.
- Assert fieldInfo.IsStatic before calling the API.
- Match F exactly to fieldInfo.FieldType.
- Re-resolve the FieldInfo with AccessTools.Field(typeof(T), name) instead of passing a stale one.
Example fix
// before
var accessor = AccessTools.StaticFieldRefAccess<Config, int>(someFieldInfo);
// after
var fi = AccessTools.Field(typeof(Config), "cacheSize");
if (fi is { IsStatic: true })
var accessor = AccessTools.StaticFieldRefAccess<Config, int>(fi); Defensive patterns
Strategy: validation
Validate before calling
if (fieldInfo is null || !fieldInfo.IsStatic || fieldInfo.FieldType != typeof(F))
throw new InvalidOperationException("FieldInfo must be a static field of type " + typeof(F)); Type guard
bool IsTypedStaticField<F>(FieldInfo fi) => fi is { IsStatic: true } && fi.FieldType == typeof(F); Try / catch
try { var r = AccessTools.StaticFieldRefAccess<T, F>(fieldInfo)(); }
catch (ArgumentException ex) { logger.Warn(ex.InnerException, "ref access failed for {0}", fieldInfo); } Prevention
- Resolve FieldInfo fresh via AccessTools.Field(typeof(T), name) rather than caching stale values.
- Verify IsStatic and FieldType before invoking.
- Catch and inspect InnerException to distinguish resolution vs invocation failures.
When it happens
Trigger: Calling AccessTools.StaticFieldRefAccess<T, F>(AccessTools.Field(typeof(T), name)) where fieldInfo is not static, F does not match the field's declared type, or the runtime ref-accessor creation/invocation throws.
Common situations: Passing an instance field's FieldInfo by mistake, generic F mismatch after a target library update changed the field type, or caching an accessor for a field that was removed.
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
- 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/5d0a46dda55fa5b7.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/AccessTools.cs:1721
/// </typeparam>
/// <param name="fieldInfo">The field</param>
/// <returns>A readable/assignable reference to the field</returns>
/// <remarks>
/// The type parameter <typeparamref name="T"/> is only used in exception messaging and to distinguish between this method overload
/// and the <see cref="StaticFieldRefAccess{F}(FieldInfo)"/> overload (which returns a <see cref="FieldRef{F}"/> rather than a reference).
/// </remarks>
///
public static ref F StaticFieldRefAccess<T, F>(FieldInfo fieldInfo)
{
if (fieldInfo is null)
throw new ArgumentNullException(nameof(fieldInfo));
try
{
return ref Tools.StaticFieldRefAccess<F>(fieldInfo)();
}
catch (Exception ex)
{
throw new ArgumentException($"StaticFieldRefAccess<{typeof(T)}, {typeof(F)}> for {fieldInfo} caused an exception", ex);
}
}
/// <summary>Creates a static field reference delegate</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="fieldInfo">The field</param>
/// <returns>A readable/assignable <see cref="FieldRef{F}"/> delegate</returns>
///
public static FieldRef<F> StaticFieldRefAccess<F>(FieldInfo fieldInfo)
{
if (fieldInfo is null)
throw new ArgumentNullException(nameof(fieldInfo));
try
{
View on GitHub (pinned to e7872dc170)