{"record":{"id":"ee40fc4d7f5dd15c","repo":"flowable/flowable-engine","slug":"error-method-literal-void","errorCode":"error.method.literal.void","errorMessage":"error.method.literal.void","messagePattern":"error\\.method\\.literal\\.void","errorType":"exception","errorClass":"ELException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/TreeMethodExpression.java","lineNumber":88,"sourceCode":"\t * @param returnType the expected return type (may be <code>null</code>)\n\t * @param paramTypes the expected parameter types (must not be <code>null</code> for lvalues)\n\t */\n\tpublic TreeMethodExpression(TreeStore store, FunctionMapper functions, VariableMapper variables, TypeConverter converter, String expr, Class<?> returnType, Class<?>[] paramTypes) {\n\t\tsuper();\n\n\t\tTree tree = store.get(expr);\n\n\t\tthis.builder = store.getBuilder();\n\t\tthis.bindings = tree.bind(functions, variables, converter);\n\t\tthis.expr = expr;\n\t\tthis.type = returnType;\n\t\tthis.types = paramTypes;\n\t\tthis.node = tree.getRoot();\n\t\tthis.deferred = tree.isDeferred();\n\n\t\tif (node.isLiteralText()) {\n\t\t\tif (returnType == void.class || returnType == Void.class) {\n\t\t\t\tthrow new ELException(LocalMessages.get(\"error.method.literal.void\", expr));\n\t\t\t}\n\t\t} else if (!node.isMethodInvocation()) {\n\t\t\tif (!node.isLeftValue()) {\n\t\t\t\tthrow new ELException(LocalMessages.get(\"error.method.invalid\", expr));\n\t\t\t}\n\t\t\tif (paramTypes == null) {\n\t\t\t\tthrow new NullPointerException(LocalMessages.get(\"error.method.notypes\")); // EL specification requires NPE\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate String getStructuralId() {\n\t\tif (structure == null) {\n\t\t\tstructure = node.getStructuralId(bindings);\n\t\t}\n\t\treturn structure;\n\t}\n\t","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/TreeMethodExpression.java#L70-L106","documentation":"TreeMethodExpression validates its expression at construction. A literal-text expression (e.g. 'someString' with no #{} or ${}) used as a method expression must have a non-void return type; throwing a literal that returns void is rejected with 'error.method.literal.void'.","triggerScenarios":"new TreeMethodExpression(..., expr, paramTypes, returnType) where expr is literal text (node.isLiteralText()) and returnType is void.class or Void.class.","commonSituations":"JSF-style action listeners or UI bindings configured with a literal string instead of a method reference; refactoring that changed a method expression into a literal while keeping a void return type.","solutions":["Change the expected return type to a non-void type (e.g. Object.class) if the literal is intentional.","Replace the literal expression with an actual method expression like '#{bean.action}' for void-returning actions.","Remove the expression binding if a constant literal was not intended to be invoked."],"exampleFix":"// before\nnew TreeMethodExpression(store, ctx, fns, vars, \"doIt\", null, void.class)\n// after\nnew TreeMethodExpression(store, ctx, fns, vars, \"#{bean.doIt}\", null, void.class)","handlingStrategy":"validation","validationCode":"if (returnType == void.class || returnType == Void.class) {\n    if (!expr.contains(\"#{\") && !expr.contains(\"${\")) {\n        throw new IllegalArgumentException(\"literal method expression cannot have void return type: \" + expr);\n    }\n}","typeGuard":"boolean isLiteralVoidMethod(String expr, Class<?> returnType) {\n    boolean literal = !(expr.startsWith(\"#{\") || expr.startsWith(\"${\"));\n    return literal && (returnType == void.class || returnType == Void.class);\n}","tryCatchPattern":"try {\n    TreeMethodExpression m = new TreeMethodExpression(store, ctx, fns, vars, expr, paramTypes, returnType);\n} catch (ELException e) {\n    // literal with void return: use a method expression or non-void returnType\n}","preventionTips":["Never pair literal-text expressions with void return types.","Use '#{bean.method}' form for void-returning actions.","Validate expression/type pairs in configuration before constructing TreeMethodExpression."],"tags":["el","method-expression","literal","flowable"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}