{"record":{"id":"9cd660c7070fc89e","repo":"pardeike/Harmony","slug":"string-join-names-available-fields-fields-available","errorCode":null,"errorMessage":"{string.Join(\",\", names)}; available fields: {fields}; available properties: {properties}","messagePattern":"(.+?); available fields: (.+?); available properties: (.+?)","errorType":"exception","errorClass":"MissingMemberException","httpStatus":null,"severity":"error","filePath":"Harmony/Tools/AccessTools.cs","lineNumber":2066,"sourceCode":"\t\tpublic static bool IsNetFrameworkRuntime { get; } =\r\n\t\t\tType.GetType(\"System.Runtime.InteropServices.RuntimeInformation\", false)?.GetProperty(\"FrameworkDescription\")\r\n\t\t\t.GetValue(null, null).ToString().StartsWith(\".NET Framework\") ?? IsMonoRuntime is false;\r\n\r\n\t\t/// <summary>True if the current runtime is .NET Core, false otherwise (Mono or .NET Framework)</summary>\r\n\t\t///\r\n\t\tpublic static bool IsNetCoreRuntime { get; } =\r\n\t\t\tType.GetType(\"System.Runtime.InteropServices.RuntimeInformation\", false)?.GetProperty(\"FrameworkDescription\")\r\n\t\t\t.GetValue(null, null).ToString().StartsWith(\".NET Core\") ?? false;\r\n\r\n\t\t/// <summary>Throws a missing member runtime exception</summary>\r\n\t\t/// <param name=\"type\">The type that is involved</param>\r\n\t\t/// <param name=\"names\">A list of names</param>\r\n\t\t///\r\n\t\tpublic static void ThrowMissingMemberException(Type type, params string[] names)\r\n\t\t{\r\n\t\t\tvar fields = string.Join(\",\", [.. GetFieldNames(type)]);\r\n\t\t\tvar properties = string.Join(\",\", [.. GetPropertyNames(type)]);\r\n\t\t\tthrow new MissingMemberException($\"{string.Join(\",\", names)}; available fields: {fields}; available properties: {properties}\");\r\n\t\t}\r\n\r\n\t\t/// <summary>Gets default value for a specific type</summary>\r\n\t\t/// <param name=\"type\">The class/type</param>\r\n\t\t/// <returns>The default value</returns>\r\n\t\t///\r\n\t\tpublic static object GetDefaultValue(Type type)\r\n\t\t{\r\n\t\t\tif (type is null)\r\n\t\t\t{\r\n\t\t\t\tFileLog.Debug(\"AccessTools.GetDefaultValue: type is null\");\r\n\t\t\t\treturn null;\r\n\t\t\t}\r\n\t\t\tif (type == typeof(void))\r\n\t\t\t\treturn null;\r\n\t\t\tif (type.IsValueType)\r\n\t\t\t\treturn Activator.CreateInstance(type);\r\n\t\t\treturn null;\r","sourceCodeStart":2048,"sourceCodeEnd":2084,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Tools/AccessTools.cs#L2048-L2084","documentation":"AccessTools.ThrowMissingMemberException throws MissingMemberException listing the requested names plus all fields and properties actually available on the type. It is Harmony's helper for 'none of these members exist' situations, designed to make diagnosing typos and renamed members easy.","triggerScenarios":"Explicitly calling AccessTools.ThrowMissingMemberException(type, names), or indirectly via AccessTools APIs that resolve one of several member names (e.g. AccessTools.DeclaredMethod/Property variants taking name arrays) when no requested member exists on the type.","commonSituations":"Target library/game updated and renamed members; typos in member names; looking for a member on a base class where only the derived class has it; confusing a property with a field.","solutions":["Read the message: pick the correct name from the listed available fields/properties.","Re-resolve members after a target update by inspecting the type with AccessTools.GetFieldNames/GetPropertyNames.","Search base types with AccessTools.GetFieldDescendants or flatten inherited members via AccessTools.GetDeclaredFields(type, includeBaseType: true).","Guard resolution with AccessTools.Field/Property null checks before use."],"exampleFix":"// before\nAccessTools.Method(typeof(Player), \"GetHelth\");\n// after\nAccessTools.Method(typeof(Player), \"GetHealth\"); // message listed 'GetHealth' among available members","handlingStrategy":"validation","validationCode":"var fi = AccessTools.Field(type, name) ?? AccessTools.Property(type, name);\nif (fi is null)\n{\n    foreach (var candidate in AccessTools.GetFieldNames(type).Concat(AccessTools.GetPropertyNames(type)))\n        Console.WriteLine(candidate); // pick correct spelling\n}","typeGuard":"bool MemberExists(Type t, string n) => AccessTools.Field(t, n) is not null || AccessTools.Property(t, n) is not null;","tryCatchPattern":"try { AccessTools.X(type, names); }\ncatch (MissingMemberException ex) { /* parse 'available fields/properties' list from ex.Message to find correct name */ }","preventionTips":["Use nameof(...) for member names instead of string literals.","After target updates, dump available names via AccessTools.GetFieldNames/GetPropertyNames.","Null-check AccessTools.Field/Property results before use."],"tags":["reflection","missing-member","harmony"],"backgroundTag":"record-not-found","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"}