{"record":{"id":"dc47b73d280b0434","repo":"flowable/flowable-engine","slug":"error-identifier-method-notamethod","errorCode":null,"errorMessage":"error.identifier.method.notamethod","messagePattern":"error\\.identifier\\.method\\.notamethod","errorType":"exception","errorClass":"MethodNotFoundException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/ast/AstIdentifier.java","lineNumber":196,"sourceCode":"\t\t\t\t\ttry {\n\t\t\t\t\t\treturn method.invoke(null, params);\n\t\t\t\t\t} catch (IllegalAccessException e) {\n\t\t\t\t\t\tthrow new ELException(LocalMessages.get(\"error.identifier.method.access\", name), e);\n\t\t\t\t\t} catch (IllegalArgumentException e) {\n\t\t\t\t\t\tthrow new ELException(LocalMessages.get(\"error.identifier.method.invocation\", name, e));\n\t\t\t\t\t} catch (InvocationTargetException e) {\n\t\t\t\t\t\tthrow new ELException(LocalMessages.get(\"error.identifier.method.invocation\", name, e.getCause()));\n\t\t\t\t\t}\n\t\t\t\t}\t\t\t\n\t\t\t\t@Override\n\t\t\t\tpublic MethodInfo getMethodInfo(ELContext context) {\n\t\t\t\t\treturn new MethodInfo(method.getName(), method.getReturnType(), method.getParameterTypes());\n\t\t\t\t}\n\t\t\t};\n\t\t} else if (value instanceof MethodExpression) {\n\t\t\treturn (MethodExpression)value;\n\t\t}\n\t\tthrow new MethodNotFoundException(LocalMessages.get(\"error.identifier.method.notamethod\", name, value.getClass()));\n\t}\n\n\t@Override\n\tpublic MethodInfo getMethodInfo(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes) {\n\t\treturn getMethodExpression(bindings, context, returnType, paramTypes).getMethodInfo(context);\n\t}\n\n\t@Override\n\tpublic Object invoke(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes, Object[] params) {\n\t\treturn getMethodExpression(bindings, context, returnType, paramTypes).invoke(context, params);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn name;\n\t}\n\n\t@Override ","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/ast/AstIdentifier.java#L178-L214","documentation":"AstIdentifier.getMethodExpression resolves an identifier to a method to invoke. If the bound value is neither a Java method/FunctionMapper result nor a MethodExpression, it throws MethodNotFoundException naming the identifier and the actual value class. It means the EL expression calls something like ${name(args)} but 'name' resolved to an ordinary object that is not callable.","triggerScenarios":"Invoking an identifier as a method in EL (e.g. ${myHelper(x)}) when the bound identifier evaluates to a plain value (String, bean, null-wrapped object) rather than a method reference or MethodExpression; bindings missing a method entry because the FunctionMapper/ELResolver did not provide one.","commonSituations":"Typo in a function name registered via EL functions; calling a bean property as a method (writing ${obj.field()} instead of ${obj.field}); a variable bound in a process/delegation was expected to be a lambda/method but is a plain serialized value; upgrading Flowable/EL versions where method resolution via resolver was removed.","solutions":["Fix the expression: use property access ${obj.field} instead of invoking it as a method, or call the method on the object ${obj.method(x)}.","Ensure the identifier is actually bound to a method (register it via the ELContext FunctionMapper or bind a LambdaExpression) instead of a plain value.","Correct the identifier spelling / variable name so it resolves to the intended callable.","Inspect the class name in the message to see what the identifier actually resolved to and adjust bindings accordingly."],"exampleFix":"// before\n${toUpperCase(name)}   // toUpperCase not a registered function\n// after\n${name.toUpperCase()}  // method call on the value","handlingStrategy":"validation","validationCode":"Object v = factory.createValueExpression(ctx, \"${name}\", Object.class).getValue(context);\nif (!(v instanceof java.lang.reflect.Method || v instanceof MethodExpression || v instanceof LambdaExpression)) {\n    throw new IllegalStateException(\"Identifier 'name' is not callable: \" + v);\n}","typeGuard":"boolean isCallable(Object v) {\n    return v instanceof java.lang.reflect.Method\n        || v instanceof MethodExpression\n        || v instanceof LambdaExpression;\n}","tryCatchPattern":null,"preventionTips":["Use property access syntax unless the identifier is a registered function or lambda","Keep function/lambda registrations in one place and validate them at startup","Check the value class printed in the message to spot binding mistakes quickly"],"tags":["el","expression-language","method-not-found"],"backgroundTag":"method-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}