flowable/flowable-engine · error · ELException
error.identifier.method.invocation
Error message
error.identifier.method.invocation
What it means
Wraps java.lang.IllegalArgumentException raised during method.invoke(null, params) — the supplied arguments do not match the method's declared parameter types, or the method is not static/invoked with wrong receiver. The reflective invocation itself failed on argument binding. Note the message includes the exception, whereas the InvocationTargetException branch unwraps the cause.
Solutions
- Match argument types to the method signature (convert numerics/strings explicitly)
- Avoid nulls for primitive parameters (use wrapper parameter types or provide defaults)
- Ensure the resolved Method is static when invoked with a null receiver
- Log/print paramTypes vs the method's getParameterTypes() to spot mismatches
Example fix
// before: expression ${calc(orders)} where orders is String "5" and calc(int)
// after: set the variable as Integer
execution.setVariable("orders", Integer.parseInt(orderCountString)); Defensive patterns
Strategy: validation
Validate before calling
Object[] args = ...;
Class<?>[] declared = method.getParameterTypes();
if (args.length != declared.length) throw new IllegalArgumentException("Arg count mismatch for " + method);
for (int i = 0; i < declared.length; i++) {
if (args[i] == null && declared[i].isPrimitive()) throw new IllegalArgumentException("Null for primitive param " + i);
} Type guard
boolean argsCompatible(Object[] args, Class<?>[] types) {
if (args.length != types.length) return false;
for (int i = 0; i < types.length; i++) {
if (args[i] == null ? types[i].isPrimitive() : !types[i].isInstance(args[i])) return false;
}
return true;
} Try / catch
try {
methodExpr.invoke(context, params);
} catch (ELException e) {
if (e.getCause() instanceof IllegalArgumentException) {
logger.error("Argument type mismatch invoking EL method: {}", e.getMessage());
}
throw e;
} Prevention
- Convert variables to the exact types the method declares before evaluation
- Use wrapper types instead of primitives for nullable EL parameters
- Validate variable types with unit tests that run real expressions
- Document expected parameter types on EL-exposed methods
When it happens
Trigger: Invoking a method expression with params whose runtime types (or count) do not match the Method's parameter types; passing null where a primitive is expected; invoking an instance method as static.
Common situations: EL expression passes a String where the delegate expects an Integer; flowable passes a DelegateExecution but the method expects a different type; primitive parameters receiving null argument values from variables.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Builder is missing constructor (can't pass features)
- Class could not be instantiated
- Class not found
- Could not get context class loader
- TreeBuilder could not be instantiated
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/676e6df57b2c3d9b.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/ast/AstIdentifier.java:183
public String getExpressionString() {
return null;
}
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object obj) {
return obj == this;
}
@Override
public Object invoke(ELContext context, Object[] params) {
try {
return method.invoke(null, params);
} catch (IllegalAccessException e) {
throw new ELException(LocalMessages.get("error.identifier.method.access", name), e);
} catch (IllegalArgumentException e) {
throw new ELException(LocalMessages.get("error.identifier.method.invocation", name, e));
} catch (InvocationTargetException e) {
throw new ELException(LocalMessages.get("error.identifier.method.invocation", name, e.getCause()));
}
}
@Override
public MethodInfo getMethodInfo(ELContext context) {
return new MethodInfo(method.getName(), method.getReturnType(), method.getParameterTypes());
}
};
} else if (value instanceof MethodExpression) {
return (MethodExpression)value;
}
throw new MethodNotFoundException(LocalMessages.get("error.identifier.method.notamethod", name, value.getClass()));
}
@Override
public MethodInfo getMethodInfo(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes) {
return getMethodExpression(bindings, context, returnType, paramTypes).getMethodInfo(context);View on GitHub (pinned to d6d39ce1c6)