{"record":{"id":"4a94349679ab713c","repo":"pardeike/Harmony","slug":"fieldrefaccess-typeof-t-typeof-f-for-instance-fieldinfo","errorCode":null,"errorMessage":"FieldRefAccess<{typeof(T)}, {typeof(F)}> for {instance}, {fieldInfo} caused an exception","messagePattern":"FieldRefAccess<(.+?), (.+?)> for (.+?), (.+?) caused an exception","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Harmony/Tools/AccessTools.cs","lineNumber":1503,"sourceCode":"\t\t\t\tvar delegateInstanceType = typeof(T);\r\n\t\t\t\tif (delegateInstanceType.IsValueType)\r\n\t\t\t\t\tthrow new ArgumentException(\"T (FieldRefAccess instance type) must not be a value type\");\r\n\t\t\t\tif (fieldInfo.IsStatic)\r\n\t\t\t\t\tthrow new ArgumentException(\"Field must not be static\");\r\n\t\t\t\tvar needCastclass = false;\r\n\t\t\t\tif (fieldInfo.DeclaringType is Type declaringType)\r\n\t\t\t\t{\r\n\t\t\t\t\t// When fieldInfo is passed to FieldRefAccess methods, the T generic class constraint is insufficient to ensure that\r\n\t\t\t\t\t// the field is not a struct instance field, since T could be object, ValueType, or an interface that the struct implements.\r\n\t\t\t\t\tif (declaringType.IsValueType)\r\n\t\t\t\t\t\tthrow new ArgumentException(\"FieldDeclaringType must be a class\");\r\n\t\t\t\t\tneedCastclass = Tools.FieldRefNeedsClasscast(delegateInstanceType, declaringType);\r\n\t\t\t\t}\r\n\t\t\t\treturn ref Tools.FieldRefAccess<T, F>(fieldInfo, needCastclass)(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($\"FieldRefAccess<{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 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\">A reference to the runtime instance to access the field</param>\r\n\t\t/// <returns>A readable/assignable reference to the field</returns>\r\n\t\t///\r\n\t\tpublic delegate ref F StructFieldRef<T, F>(ref T instance) where T : struct;\r\n\r\n\t\t/// <summary>Creates a field reference delegate 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","sourceCodeStart":1485,"sourceCodeEnd":1521,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Tools/AccessTools.cs#L1485-L1521","documentation":"Catch-all wrapper in the instance-taking AccessTools.FieldRefAccess<T,F>(fieldInfo, instance): any failure while creating or invoking the ref delegate is rethrown as an ArgumentException naming T, F, the instance and the FieldInfo, with the real exception as InnerException.","triggerScenarios":"Any of: T is a value type, field is static, field's declaring type is a struct, or the returned delegate fails when invoked with an incompatible/null instance.","commonSituations":"Passing a null or wrong-typed instance to the returned delegate; patch setup errors during startup where the inner exception is the actual diagnosis.","solutions":["Log and inspect ex.InnerException for the root cause","Ensure instance is a live (non-null) object of type T or derived","Confirm fieldInfo is a non-static instance field on a class","Pre-validate T/fieldInfo/instance before calling (IsValueType, IsStatic, DeclaringType checks)"],"exampleFix":"// before\nvar rf = AccessTools.FieldRefAccess<T, F>(fi);\nref var v = ref rf(instance);\n// after\nif (fi.DeclaringType is { IsValueType: true }) throw new NotSupportedException(\"use StructFieldRefAccess\");\nvar rf = AccessTools.FieldRefAccess<T, F>(fi);\nref var v = ref rf(instance ?? throw new InvalidOperationException(\"instance is null\"));","handlingStrategy":"try-catch","validationCode":"if (instance is null) throw new ArgumentNullException(nameof(instance));\nif (typeof(T).IsValueType || fieldInfo is { IsStatic: true } || fieldInfo.DeclaringType is { IsValueType: true }) throw new ArgumentException(\"invalid FieldRefAccess parameters\");","typeGuard":"static bool IsValidClassFieldRef<T, F>(FieldInfo fi) => !typeof(T).IsValueType && fi is { IsStatic: false } && fi.DeclaringType is { IsValueType: false };","tryCatchPattern":"try { var rf = AccessTools.FieldRefAccess<T, F>(fi); return rf(instance); }\ncatch (ArgumentException ex) { throw new InvalidOperationException(\"FieldRefAccess failed\", ex.InnerException ?? ex); }","preventionTips":["Ensure the instance is non-null and exactly type T or derived","Cache delegates per (T, fieldInfo) pair, never across types","Validate all three inputs (T, fieldInfo, instance) before building refs"],"tags":["harmony","reflection","fieldref","wrapper"],"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"}