{"record":{"id":"2ab9d5b04eeafad9","repo":"flowable/flowable-engine","slug":"error-property-method-invocation","errorCode":null,"errorMessage":"error.property.method.invocation","messagePattern":"error\\.property\\.method\\.invocation","errorType":"exception","errorClass":"ELException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/ast/AstProperty.java","lineNumber":217,"sourceCode":"\n\t@Override\n\tpublic Object invoke(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes, Object[] paramValues) {\n\t\tObject base = prefix.eval(bindings, context);\n\t\tif (base == null) {\n\t\t\tthrow new PropertyNotFoundException(LocalMessages.get(\"error.property.base.null\", prefix));\n\t\t}\n\t\tObject property = getProperty(bindings, context);\n\t\tif (property == null && strict) {\n\t\t\tthrow new PropertyNotFoundException(LocalMessages.get(\"error.property.method.notfound\", \"null\", base));\n\t\t}\n\t\tString name = bindings.convert(property, String.class);\n\t\tMethod method = findMethod(name, base.getClass(), returnType, paramTypes);\n\t\ttry {\n\t\t\treturn method.invoke(base, paramValues);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tthrow new ELException(LocalMessages.get(\"error.property.method.access\", name, base.getClass()), e);\n\t\t} catch (IllegalArgumentException e) {\n\t\t\tthrow new ELException(LocalMessages.get(\"error.property.method.invocation\", name, base.getClass()), e);\n\t\t} catch (InvocationTargetException e) {\n\t\t\tthrow new ELException(LocalMessages.get(\"error.property.method.invocation\", name, base.getClass()), e.getCause());\n\t\t}\n\t}\n\n\t@Override\n\tpublic AstNode getChild(int i) {\n\t\treturn i == 0 ? prefix : null;\n\t}\n}\n","sourceCodeStart":199,"sourceCodeEnd":228,"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/AstProperty.java#L199-L228","documentation":"ELException (error.property.method.invocation) thrown when Method.invoke raises IllegalArgumentException — the actual argument values supplied to the expression do not match the method's declared parameter types. It carries the original exception as cause.","triggerScenarios":"invoke() on ${obj.method(a, b)} where an argument's runtime type is incompatible with the method signature (e.g. passing a String where an int/Long is expected, or wrong number of arguments).","commonSituations":"EL coercion not converting types as expected (string literals vs numbers); changed method signatures after expression deployment; passing null to primitive parameters; type erasure surprises with collections.","solutions":["Match argument types to the method signature, adding explicit conversions in the expression if needed.","Change the method to accept the types actually passed (e.g. Object, Number, or a wrapper).","Convert values before evaluation (set variables of the correct type in the ELContext).","Ensure the argument count matches the declared parameters, including varargs handling."],"exampleFix":"// before\n${calc.add(\"1\", 2)} // add(int, int) — String literal fails\n// after\n${calc.add(1, 2)}","handlingStrategy":"validation","validationCode":"java.lang.reflect.Method m = base.getClass().getMethod(\"add\", int.class, int.class);\nfor (Object arg : args) {\n    if (arg instanceof String && m.getParameterTypes()[0] == int.class) {\n        throw new IllegalArgumentException(\"pass numeric literals in EL, not strings\");\n    }\n}","typeGuard":"boolean argsMatch(java.lang.reflect.Method m, Object... args) {\n    Class<?>[] pts = m.getParameterTypes();\n    if (args.length != pts.length) return false;\n    for (int i = 0; i < pts.length; i++) {\n        if (args[i] != null && !pts[i].isInstance(args[i])\n            && !isCoercible(args[i], pts[i])) return false;\n    }\n    return true;\n}","tryCatchPattern":"try {\n    result = expr.invoke(ctx);\n} catch (jakarta.el.ELException e) {\n    if (e.getCause() instanceof IllegalArgumentException) {\n        log.warn(\"EL argument type mismatch: {}\", e.getMessage());\n        throw new IllegalStateException(\"fix argument types in expression\", e);\n    }\n    throw e;\n}","preventionTips":["Use unquoted numeric literals for numeric parameters in EL","Add tests exercising each EL expression with realistic argument types","Coerce types in the backing bean (accept Number/Object) to be lenient","Keep EL expressions in sync with signature changes via integration tests"],"tags":["java","el","reflection","argument-types"],"backgroundTag":"type-mismatch","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"}