pardeike/Harmony · error · ArgumentException
Member must be of type EventInfo, FieldInfo, MethodInfo, or…
Error message
Member must be of type EventInfo, FieldInfo, MethodInfo, or PropertyInfo
What it means
AccessTools.GetUnderlyingType throws this ArgumentException when the MemberInfo passed to it is not an EventInfo, FieldInfo, MethodInfo, or PropertyInfo (e.g. it is a Type, ConstructorInfo, or nested type). The switch over MemberTypes has no matching case for such members, so Harmony throws to signal an unusable input. The method only computes 'the type of data a member holds/returns', which does not exist for other member kinds.
Solutions
- Verify member.MemberType is one of MemberTypes.Event/Field/Method/Property before calling GetUnderlyingType
- Filter collections with .Where(m => m is not ConstructorInfo and not Type) before processing
- Use member.GetType()-specific APIs (e.g. ConstructorInfo has no return type) for other member kinds
Example fix
// before var t = AccessTools.GetUnderlyingType(AccessTools.Constructor(typeof(Foo))); // after MemberInfo mi = AccessTools.Method(typeof(Foo), "Bar"); var t = mi is ConstructorInfo ? null : AccessTools.GetUnderlyingType(mi);
Defensive patterns
Strategy: type-guard
Validate before calling
if (member is not (EventInfo or FieldInfo or MethodInfo or PropertyInfo)) throw new ArgumentException($"Unsupported member: {member?.GetType().Name}"); Type guard
bool SupportsGetUnderlyingType(MemberInfo m) => m is EventInfo or FieldInfo or MethodInfo or PropertyInfo;
Prevention
- Filter MemberInfo collections before calling GetUnderlyingType
- Never pass ConstructorInfo or nested Types into it
- Assert member.MemberType with a debug check in shared patch helpers
When it happens
Trigger: Calling AccessTools.GetUnderlyingType with a ConstructorInfo (e.g. obtained from AccessTools.Constructor), a Type object, a nested type, or any MemberInfo whose MemberType is not Event/Field/Method/Property.
Common situations: Passing the result of AccessTools.Constructor or AccessTools.TypeByName into GetUnderlyingType, or generically processing MemberInfo collections that include constructors and nested types.
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
- The type must declare an empty constructor (the constructor…
- Value cannot be null. (Parameter 'fromMethod')
- Value cannot be null. (Parameter 'method')
- Value cannot be null. (Parameter 'config.original')
- cannot contain zeros
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/3fa6b048f241b522.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Tools/AccessTools.cs:912
FileLog.Debug("AccessTools.GetPropertyNames: instance is null");
return [];
}
return GetPropertyNames(instance.GetType());
}
/// <summary>Gets the type of any class member of</summary>
/// <param name="member">A member</param>
/// <returns>The class/type of this member</returns>
///
public static Type GetUnderlyingType(this MemberInfo member)
{
return member.MemberType switch
{
MemberTypes.Event => ((EventInfo)member).EventHandlerType,
MemberTypes.Field => ((FieldInfo)member).FieldType,
MemberTypes.Method => ((MethodInfo)member).ReturnType,
MemberTypes.Property => ((PropertyInfo)member).PropertyType,
_ => throw new ArgumentException("Member must be of type EventInfo, FieldInfo, MethodInfo, or PropertyInfo"),
};
}
/// <summary>Returns a <see cref="MethodInfo"/> by searching for module-id and token</summary>
/// <param name="moduleGUID">The module of the method</param>
/// <param name="token">The token of the method</param>
/// <returns></returns>
public static MethodInfo GetMethodByModuleAndToken(string moduleGUID, int token)
{
#if NET5_0_OR_GREATER
Module module = null;
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var moduleVersionGUID = new Guid(moduleGUID);
Parallel.ForEach(assemblies, (assembly) =>
{
var allModules = assembly.GetModules();
for (var i = 0; i < allModules.Length; i++)
if (allModules[i].ModuleVersionId == moduleVersionGUID)
View on GitHub (pinned to e7872dc170)