{"record":{"id":"b6a35a5cfce88b67","repo":"pardeike/Harmony","slug":"cannot-find-method-for-expression-expression","errorCode":null,"errorMessage":"Cannot find method for expression {expression}","messagePattern":"Cannot find method for expression (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Harmony/Tools/SymbolExtensions.cs","lineNumber":49,"sourceCode":"\r\n\t\t/// <summary>Given a lambda expression that calls a method, returns the method info</summary>\r\n\t\t/// <param name=\"expression\">The lambda expression using the method</param>\r\n\t\t/// <returns>The method in the lambda expression</returns>\r\n\t\t///\r\n\t\tpublic static MethodInfo GetMethodInfo(LambdaExpression expression)\r\n\t\t{\r\n\t\t\tvar outermostExpression = expression.Body as MethodCallExpression;\r\n\r\n\t\t\tif (outermostExpression is null)\r\n\t\t\t{\r\n\t\t\t\tif (expression.Body is UnaryExpression ue && ue.Operand is MethodCallExpression me && me.Object is System.Linq.Expressions.ConstantExpression ce && ce.Value is MethodInfo mi)\r\n\t\t\t\t\treturn mi;\r\n\t\t\t\tthrow new ArgumentException(\"Invalid Expression. Expression should consist of a Method call only.\");\r\n\t\t\t}\r\n\r\n\t\t\tvar method = outermostExpression.Method;\r\n\t\t\tif (method is null)\r\n\t\t\t\tthrow new Exception($\"Cannot find method for expression {expression}\");\r\n\r\n\t\t\treturn method;\r\n\t\t}\r\n\r\n\t\t/// <summary>Given a lambda expression that accesses a field, returns the field info</summary>\r\n\t\t/// <typeparam name=\"T\">The generic field type</typeparam>\r\n\t\t/// <param name=\"expression\">The lambda expression using the field</param>\r\n\t\t/// <returns>The field in the lambda expression</returns>\r\n\t\t///\r\n\t\tpublic static FieldInfo GetFieldInfo<T>(Expression<Func<T>> expression) => GetFieldInfo((LambdaExpression)expression);\r\n\r\n\t\t/// <summary>Given a lambda expression that accesses a field, returns the field info</summary>\r\n\t\t/// <param name=\"expression\">The lambda expression using the field</param>\r\n\t\t/// <returns>The field in the lambda expression</returns>\r\n\t\t///\r\n\t\tpublic static FieldInfo GetFieldInfo(LambdaExpression expression)\r\n\t\t{\r\n\t\t\tif (expression is null)\r","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Tools/SymbolExtensions.cs#L31-L67","documentation":"GetMethodInfo succeeded in finding a MethodCallExpression in the lambda, but its .Method property was null. This happens in rare cases (e.g. reduced dynamic call nodes) where the call node exists but no concrete MethodInfo can be resolved. Harmony throws a plain Exception with the offending expression in the message.","triggerScenarios":"Passing an Expression<Func<T>> whose body is a MethodCallExpression with a null Method property — practically only seen with unusual/dynamic call expressions or compiler-generated reduced nodes, not ordinary lambdas.","commonSituations":"Extremely rare in normal use; typically encountered when building expression trees manually (Expression.Call with a null method) or with exotic dynamic proxies feeding GetMethodInfo.","solutions":["Verify the lambda uses a normal, compile-time-resolvable method call rather than a manually constructed expression tree","If building expressions by hand, ensure Expression.Call receives a non-null MethodInfo before passing the lambda to GetMethodInfo","Bypass the helper: capture the MethodInfo directly (typeof(T).GetMethod(\"Name\", flags)) instead of via expression"],"exampleFix":"// before\nvar expr = Expression.Lambda<Func<int>>(Expression.Call(default(MethodInfo)));\nvar m = SymbolExtensions.GetMethodInfo(expr);\n// after\nvar m = typeof(SomeType).GetMethod(\"Target\", BindingFlags.Public | BindingFlags.Static);","handlingStrategy":"try-catch","validationCode":"if (expr.Body is MethodCallExpression { Method: null })\n    throw new InvalidOperationException(\"Expression tree has a call node without a MethodInfo\");","typeGuard":"static MethodInfo SafeMethod(LambdaExpression e) =>\n    (e.Body as MethodCallExpression)?.Method ??\n    (e.Body as UnaryExpression)?.Operand is MethodCallExpression m ? m.Method : null;","tryCatchPattern":"MethodInfo mi;\ntry { mi = SymbolExtensions.GetMethodInfo(expr); }\ncatch (Exception) { mi = typeof(T).GetMethod(\"Name\", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); }","preventionTips":["Avoid hand-built or reduced expression trees with GetMethodInfo; use plain compile-time lambdas","Ensure Expression.Call always receives a non-null MethodInfo when constructing trees manually","Keep a name-based reflection fallback ready for exotic expression shapes"],"tags":["reflection","expression-tree","internal-invariant"],"backgroundTag":"internal-invariant-violation","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"}