{"record":{"id":"b3f5718bc76ad507","repo":"pardeike/Harmony","slug":"structfieldrefaccess-typeof-t-typeof-f-for-instance-b3f571","errorCode":null,"errorMessage":"StructFieldRefAccess<{typeof(T)}, {typeof(F)}> for {instance}, {fieldInfo} caused an exception","messagePattern":"StructFieldRefAccess<(.+?), (.+?)> for (.+?), (.+?) caused an exception","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Harmony/Tools/AccessTools.cs","lineNumber":1635,"sourceCode":"\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\n\t\t/// </para>\r\n\t\t/// </remarks>\r\n\t\t///\r\n\t\tpublic static ref F StructFieldRefAccess<T, F>(ref T instance, 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 ref Tools.StructFieldRefAccess<T, F>(fieldInfo)(ref instance);\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 {instance}, {fieldInfo} caused an exception\", ex);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/// <summary>A readable/assignable reference delegate to a static field</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/// <returns>A readable/assignable reference to the field</returns>\r\n\t\t///\r\n\t\tpublic delegate ref F FieldRef<F>();\r\n\r\n\t\t/// <summary>Creates a static field reference</summary>\r\n\t\t/// <typeparam name=\"T\">The type (can be class or struct) the field is defined in</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","sourceCodeStart":1617,"sourceCodeEnd":1653,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Tools/AccessTools.cs#L1617-L1653","documentation":"Catch-all wrapper in the instance-taking StructFieldRefAccess<T,F>(fieldInfo)(ref instance): any failure during validation or delegate creation/invocation is rethrown as an ArgumentException naming T, F, the instance and the FieldInfo, with the cause as InnerException.","triggerScenarios":"Same conditions as error 88 (wrong declaring type, static field, F type mismatch) raised from the overload that applies the ref delegate to a specific struct instance.","commonSituations":"Using a cached delegate built for one struct type against another struct's instance; target library type changed from class to struct (or vice versa) across versions.","solutions":["Check ex.InnerException for the actual failure","Re-validate fieldInfo against typeof(T) and typeof(F) at the call site","Do not reuse cached field delegates across different struct types","Pin the expected target assembly version and re-verify FieldInfo after updates"],"exampleFix":"// before\nref var v = ref AccessTools.StructFieldRefAccess<OtherStruct, int>(fi)(ref instance); // wrong struct type\n// after\nref var v = ref AccessTools.StructFieldRefAccess<MyStruct, int>(fi)(ref instance);","handlingStrategy":"validation","validationCode":"if (fi.DeclaringType != typeof(T) || fi.IsStatic || fi.FieldType != typeof(F)) throw new ArgumentException(\"invalid struct field ref arguments\");","typeGuard":"static bool MatchesStruct<T>(FieldInfo fi) where T : struct => fi.DeclaringType == typeof(T) && !fi.IsStatic && fi.FieldType == typeof(F);","tryCatchPattern":"try { ref var v = ref AccessTools.StructFieldRefAccess<T, F>(fi)(ref instance); }\ncatch (ArgumentException ex) { throw new InvalidOperationException(\"StructFieldRefAccess failed\", ex.InnerException ?? ex); }","preventionTips":["Never reuse cached struct field delegates across different struct types","Pin and verify the target assembly version before caching accessors","Validate FieldInfo once at startup and reuse the validated pair (fi, delegate)"],"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"}