flowable/flowable-engine · error · org.activiti.engine.ActivitiException

couldn't invoke ${methodName} on ${target}

Error message

couldn't invoke ${methodName} on ${target}

What it means

ReflectUtil.invoke() wraps any Exception raised while reflectively locating and calling a method via method.invoke(). The ActivitiException names the method and target object and chains the underlying cause (typically NoSuchMethodException from findMethod, or IllegalArgumentException/InvocationTargetException from the call itself). It is thrown because the engine cannot report reflection failures without knowing the method name and receiver.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/util/ReflectUtil.java:147

    }

    public static Object instantiate(String className) {
        try {
            Class<?> clazz = loadClass(className);
            return clazz.newInstance();
        } catch (Exception e) {
            throw new ActivitiException("couldn't instantiate class " + className, e);
        }
    }

    public static Object invoke(Object target, String methodName, Object[] args) {
        try {
            Class<? extends Object> clazz = target.getClass();
            Method method = findMethod(clazz, methodName, args);
            method.setAccessible(true);
            return method.invoke(target, args);
        } catch (Exception e) {
            throw new ActivitiException("couldn't invoke " + methodName + " on " + target, e);
        }
    }

    /**
     * Returns the field of the given object or null if it doesnt exist.
     */
    public static Field getField(String fieldName, Object object) {
        return getField(fieldName, object.getClass());
    }

    /**
     * Returns the field of the given class or null if it doesnt exist.
     */
    public static Field getField(String fieldName, Class<?> clazz) {
        Field field = null;
        try {
            field = clazz.getDeclaredField(fieldName);
        } catch (SecurityException e) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Check the chained cause exception for the real reflection failure
  2. Verify the method name spelling and that it exists on the target's class (use findMethod/BeanUtils semantics)
  3. Ensure the args array matches the method's parameter types exactly
  4. If running under strong encapsulation (Java 9+), add the necessary --add-opens flags or avoid reflective invocation

Example fix

// before
Object result = ReflectUtil.invoke(processInstance, "getProcessDefinicion", null); // typo, wrong name
// after
Object result = ReflectUtil.invoke(processInstance, "getProcessDefinition", null);
Defensive patterns

Strategy: try-catch

Validate before calling

// before invoking
Method m = target.getClass().getMethod(methodName);
if (m == null) throw new IllegalStateException("method " + methodName + " missing on " + target.getClass());

Type guard

boolean canInvoke(Object target, String name) {
  try { target.getClass().getDeclaredMethod(name); return true; }
  catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
  Object r = ReflectUtil.invoke(target, methodName, args);
} catch (ActivitiException e) {
  logger.error("reflective invoke failed for " + methodName + " on " + target, e.getCause());
  // fallback path
}

Prevention

When it happens

Trigger: ReflectUtil.invoke(target, methodName, args) is called when the target class has no matching declared method, the method is not accessible, or the method itself throws; args do not match parameters (findMethod has no parameter matching).

Common situations: Calling an internal hook/callback method whose signature changed between engine versions; passing wrong argument count/types; invoking methods on proxy or restricted classes where setAccessible fails under a SecurityManager or JPMS module restrictions.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/f33aa8b4613cb016. Report an issue: GitHub.