{"record":{"id":"046b4e382f6f6288","repo":"pardeike/Harmony","slug":"staticfieldrefaccess-typeof-f-for-fieldinfo-caused-an","errorCode":null,"errorMessage":"StaticFieldRefAccess<{typeof(F)}> for {fieldInfo} caused an exception","messagePattern":"StaticFieldRefAccess<(.+?)> for (.+?) caused an exception","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Harmony/Tools/AccessTools.cs","lineNumber":1744,"sourceCode":"\t\t/// <typeparam name=\"F\">\r\n\t\t/// 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),\r\n\t\t/// a type that <see cref=\"Type.IsAssignableFrom(Type)\">is assignable from</see> that type; or if the field's type is an enum type,\r\n\t\t/// either that type or the underlying integral type of that enum type\r\n\t\t/// </typeparam>\r\n\t\t/// <param name=\"fieldInfo\">The field</param>\r\n\t\t/// <returns>A readable/assignable <see cref=\"FieldRef{F}\"/> delegate</returns>\r\n\t\t///\r\n\t\tpublic static FieldRef<F> StaticFieldRefAccess<F>(FieldInfo fieldInfo)\r\n\t\t{\r\n\t\t\tif (fieldInfo is null)\r\n\t\t\t\tthrow new ArgumentNullException(nameof(fieldInfo));\r\n\t\t\ttry\r\n\t\t\t{\r\n\t\t\t\treturn Tools.StaticFieldRefAccess<F>(fieldInfo);\r\n\t\t\t}\r\n\t\t\tcatch (Exception ex)\r\n\t\t\t{\r\n\t\t\t\tthrow new ArgumentException($\"StaticFieldRefAccess<{typeof(F)}> for {fieldInfo} caused an exception\", ex);\r\n\t\t\t}\r\n\t\t}\r\n\r\n#pragma warning disable CS1591\r\n\t\t[Obsolete(\"This overload only exists for runtime backwards compatibility and will be removed in Harmony 3. Use MethodDelegate(MethodInfo, object, bool, Type[]) instead\")]\r\n\t\t[EditorBrowsable(EditorBrowsableState.Never)]\r\n\t\tpublic static DelegateType MethodDelegate<DelegateType>(MethodInfo method, object instance, bool virtualCall) where DelegateType : Delegate\r\n\t\t\t => MethodDelegate<DelegateType>(method, instance, virtualCall, null);\r\n#pragma warning restore CS1591\r\n\r\n\t\t/// <summary>Creates a delegate to a given method</summary>\r\n\t\t/// <typeparam name=\"DelegateType\">The delegate Type</typeparam>\r\n\t\t/// <param name=\"method\">The method to create a delegate from.</param>\r\n\t\t/// <param name=\"instance\">\r\n\t\t/// Only applies for instance methods. If <c>null</c> (default), returned delegate is an open (a.k.a. unbound) instance delegate\r\n\t\t/// where an instance is supplied as the first argument to the delegate invocation; else, delegate is a closed (a.k.a. bound)\r\n\t\t/// instance delegate where the delegate invocation always applies to the given <paramref name=\"instance\"/>.\r\n\t\t/// </param>\r","sourceCodeStart":1726,"sourceCodeEnd":1762,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Tools/AccessTools.cs#L1726-L1762","documentation":"AccessTools.StaticFieldRefAccess<F>(fieldInfo) wraps any exception from creating the delegate-returning ref accessor in an ArgumentException. This overload returns the accessor delegate itself, so failures here mean the FieldInfo could not be compiled into a ref getter.","triggerScenarios":"Calling AccessTools.StaticFieldRefAccess<F>(fieldInfo) with a non-static FieldInfo, a FieldInfo whose type differs from F, or an otherwise unusable FieldInfo (e.g. from a dynamic/collected type).","commonSituations":"Mixing up the delegate-returning overload with the ref-returning one, passing null or a FieldInfo resolved from a different declaring type, F not matching after a target update.","solutions":["Check InnerException for the actual failure.","Verify fieldInfo is non-null and IsStatic.","Ensure F equals fieldInfo.FieldType.","Resolve the FieldInfo via AccessTools.Field on the correct declaring type."],"exampleFix":"// before\nvar getter = AccessTools.StaticFieldRefAccess<float>(instanceFieldInfo);\n// after\nvar fi = AccessTools.Field(typeof(Physics), \"gravity\");\nvar getter = AccessTools.StaticFieldRefAccess<float>(fi); // gravity is static float","handlingStrategy":"validation","validationCode":"if (fieldInfo is null || !fieldInfo.IsStatic || fieldInfo.FieldType != typeof(F))\n    return null; // skip creating accessor\nvar getter = AccessTools.StaticFieldRefAccess<F>(fieldInfo);","typeGuard":"bool CanMakeRefAccessor<F>(FieldInfo fi) => fi is { IsStatic: true } && fi.FieldType == typeof(F);","tryCatchPattern":"try { var getter = AccessTools.StaticFieldRefAccess<F>(fieldInfo); }\ncatch (ArgumentException ex) { logger.Warn(ex.InnerException, \"cannot build accessor for {0}\", fieldInfo); }","preventionTips":["Do not confuse the delegate-returning overload with the ref-returning overload.","Check IsStatic/FieldType before use.","Re-resolve FieldInfo on the declaring type after target updates."],"tags":["reflection","static-field","harmony"],"backgroundTag":"invalid-argument-value","analyzedSha":"e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c","analyzedAt":"2026-09-15T22:47:11.550Z","contentChangedAt":"2026-09-15T22:47:11.550Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}