{"record":{"id":"5d0a46dda55fa5b7","repo":"pardeike/Harmony","slug":"staticfieldrefaccess-typeof-t-typeof-f-for-fieldinfo-caused","errorCode":null,"errorMessage":"StaticFieldRefAccess<{typeof(T)}, {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":1721,"sourceCode":"\t\t/// </typeparam>\r\n\t\t/// <param name=\"fieldInfo\">The field</param>\r\n\t\t/// <returns>A readable/assignable reference to the field</returns>\r\n\t\t/// <remarks>\r\n\t\t/// The type parameter <typeparamref name=\"T\"/> is only used in exception messaging and to distinguish between this method overload\r\n\t\t/// and the <see cref=\"StaticFieldRefAccess{F}(FieldInfo)\"/> overload (which returns a <see cref=\"FieldRef{F}\"/> rather than a reference).\r\n\t\t/// </remarks>\r\n\t\t///\r\n\t\tpublic static ref F StaticFieldRefAccess<T, 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 ref 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(T)}, {typeof(F)}> for {fieldInfo} caused an exception\", ex);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/// <summary>Creates a static field reference delegate</summary>\r\n\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","sourceCodeStart":1703,"sourceCodeEnd":1739,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Tools/AccessTools.cs#L1703-L1739","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar accessor = AccessTools.StaticFieldRefAccess<Config, int>(someFieldInfo);\n// after\nvar fi = AccessTools.Field(typeof(Config), \"cacheSize\");\nif (fi is { IsStatic: true })\n    var accessor = AccessTools.StaticFieldRefAccess<Config, int>(fi);","handlingStrategy":"validation","validationCode":"if (fieldInfo is null || !fieldInfo.IsStatic || fieldInfo.FieldType != typeof(F))\n    throw new InvalidOperationException(\"FieldInfo must be a static field of type \" + typeof(F));","typeGuard":"bool IsTypedStaticField<F>(FieldInfo fi) => fi is { IsStatic: true } && fi.FieldType == typeof(F);","tryCatchPattern":"try { var r = AccessTools.StaticFieldRefAccess<T, F>(fieldInfo)(); }\ncatch (ArgumentException ex) { logger.Warn(ex.InnerException, \"ref access failed for {0}\", fieldInfo); }","preventionTips":["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."],"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"}