{"record":{"id":"ac951837c846ff16","repo":"pardeike/Harmony","slug":"structfieldrefaccess-typeof-t-typeof-f-for-fieldinfo-caused","errorCode":null,"errorMessage":"StructFieldRefAccess<{typeof(T)}, {typeof(F)}> for {fieldInfo} caused an exception","messagePattern":"StructFieldRefAccess<(.+?), (.+?)> for (.+?) caused an exception","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Harmony/Tools/AccessTools.cs","lineNumber":1602,"sourceCode":"\t\t/// <remarks>\r\n\t\t/// <para>\r\n\t\t/// This method is meant for cases where the field has already been obtained, avoiding the field searching cost in\r\n\t\t/// e.g. <see cref=\"StructFieldRefAccess{T, F}(string)\"/>.\r\n\t\t/// </para>\r\n\t\t/// </remarks>\r\n\t\t///\r\n\t\tpublic static StructFieldRef<T, F> StructFieldRefAccess<T, F>(FieldInfo fieldInfo) where T : struct\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\tTools.ValidateStructField<T, F>(fieldInfo);\r\n\t\t\t\treturn Tools.StructFieldRefAccess<T, 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($\"StructFieldRefAccess<{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 field reference for an instance field of a struct</summary>\r\n\t\t/// <typeparam name=\"T\">The struct that defines the instance field</typeparam>\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=\"instance\">The instance</param>\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/// <para>\r\n\t\t/// This method is meant for one-off access to a field's value for a single instance and where the field has already been obtained.\r\n\t\t/// If you need to access a field's value for potentially multiple instances, use <see cref=\"StructFieldRefAccess{T, F}(FieldInfo)\"/> instead.\r\n\t\t/// <c>StructFieldRefAccess&lt;T, F&gt;(ref instance, fieldInfo)</c> is functionally equivalent to <c>StructFieldRefAccess&lt;T, F&gt;(fieldInfo)(ref instance)</c>.\r","sourceCodeStart":1584,"sourceCodeEnd":1620,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Tools/AccessTools.cs#L1584-L1620","documentation":"Catch-all wrapper in AccessTools.StructFieldRefAccess<T,F>(fieldInfo): after Tools.ValidateStructField<T,F>(fieldInfo) and delegate creation fail for any reason, the exception is rethrown as an ArgumentException naming T, F and the FieldInfo, with the original exception as InnerException.","triggerScenarios":"fieldInfo's declaring type is not T (or T not assignable to it), the field is static, fieldInfo.FieldType != typeof(F), or delegate emission fails in Tools.StructFieldRefAccess.","commonSituations":"Passing a FieldInfo discovered on a derived class while T is the struct base; generic reflection code reusing a FieldInfo across types; F declared as object instead of the exact field type.","solutions":["Confirm fieldInfo.DeclaringType == typeof(T) (or T-reachable) and the field is an instance field","Make typeof(F) exactly match fieldInfo.FieldType","Inspect ex.InnerException to see whether validation or emission failed","Validate with Tools.ValidateStructField-equivalent checks (IsValueType, !IsStatic, FieldType) before calling"],"exampleFix":"// before\nvar rf = AccessTools.StructFieldRefAccess<MyStruct, object>(fi); // F mismatch\n// after\nvar rf = AccessTools.StructFieldRefAccess<MyStruct, int>(fi); // F matches FieldType","handlingStrategy":"validation","validationCode":"if (fieldInfo is null) throw new ArgumentNullException(nameof(fieldInfo));\nif (fieldInfo.IsStatic) throw new ArgumentException(\"struct field refs require instance fields\");\nif (!typeof(T).IsValueType || fieldInfo.DeclaringType != typeof(T)) throw new ArgumentException(\"fieldInfo must be an instance field declared on struct T\");\nif (fieldInfo.FieldType != typeof(F)) throw new ArgumentException(\"F must match the field type\");","typeGuard":"static bool IsValidStructField<T, F>(FieldInfo fi) where T : struct => typeof(T).IsValueType && fi is { IsStatic: false } && fi.DeclaringType == typeof(T) && fi.FieldType == typeof(F);","tryCatchPattern":null,"preventionTips":["Mirror Tools.ValidateStructField checks at your own boundary","Only pass FieldInfos resolved directly from typeof(T)","Declare F as the exact field type, not a boxed-compatible type"],"tags":["harmony","reflection","struct","fieldref"],"backgroundTag":"type-mismatch","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"}