flowable/flowable-engine · error · ActivitiException

Exception while invoking '%s' on class %s

Error message

Exception while invoking '%s' on class %s

What it means

If the setter itself throws an exception while being invoked reflectively, Method.invoke wraps it in InvocationTargetException. ClassDelegate unwraps the situation into this ActivitiException ('Exception while invoking ...'), preserving the cause, since a failing setter means the delegate cannot be initialized safely.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java:275

    }

    public static void applyFieldDeclaration(FieldDeclaration declaration, Object target) {
        applyFieldDeclaration(declaration, target, true);
    }

    public static void applyFieldDeclaration(FieldDeclaration declaration, Object target, boolean throwExceptionOnMissingField) {
        Method setterMethod = ReflectUtil.getSetter(declaration.getName(),
                target.getClass(), declaration.getValue().getClass());

        if (setterMethod != null) {
            try {
                setterMethod.invoke(target, declaration.getValue());
            } catch (IllegalArgumentException e) {
                throw new ActivitiException("Error while invoking '" + declaration.getName() + "' on class " + target.getClass().getName(), e);
            } catch (IllegalAccessException e) {
                throw new ActivitiException("Illegal access when calling '" + declaration.getName() + "' on class " + target.getClass().getName(), e);
            } catch (InvocationTargetException e) {
                throw new ActivitiException("Exception while invoking '" + declaration.getName() + "' on class " + target.getClass().getName(), e);
            }
        } else {
            Field field = ReflectUtil.getField(declaration.getName(), target);
            if (field == null) {
                if (throwExceptionOnMissingField) {
                    throw new ActivitiIllegalArgumentException("Field definition uses unexisting field '" + declaration.getName() + "' on class " + target.getClass().getName());
                } else {
                    return;
                }
            }

            // Check if the delegate field's type is correct
            if (!fieldTypeCompatible(declaration, field)) {
                throw new ActivitiIllegalArgumentException("Incompatible type set on field declaration '" + declaration.getName()
                        + "' for class " + target.getClass().getName()
                        + ". Declared value has type " + declaration.getValue().getClass().getName()
                        + ", while expecting " + field.getType().getName());
            }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Read the cause chain (getCause() of the ActivitiException) to find the original exception inside the setter and fix that logic/value.
  2. Make the setter defensive: validate/convert the injected value and fail with a clear message.
  3. Correct the field value in the BPMN XML or Spring config so the setter succeeds.

Example fix

// before
public void setRatio(String ratio) { this.ratio = Integer.parseInt(ratio); } // throws on "0.5"
// after
public void setRatio(String ratio) { this.ratio = Double.parseDouble(ratio); }
Defensive patterns

Strategy: try-catch

Validate before calling

// smoke-test the setter before deployment:
new DelegateClass().setMyField(testValue); // should not throw for valid config values

Type guard

null

Try / catch

try {
  applyFieldDeclaration(declaration, target, throwExceptionOnMissingField);
} catch (ActivitiException e) {
  if (e.getMessage().startsWith("Exception while invoking")) {
    Throwable root = e.getCause(); // original setter failure
    log.error("Setter {} threw {}", declaration.getName(), root, e);
  } else throw e;
}

Prevention

When it happens

Trigger: The delegate's setter (matched by name for the activiti:field declaration) throws any RuntimeException/Error during injection - e.g. parsing a bad value, NPE on a dependency, validation inside the setter.

Common situations: Setter performs Integer.parseInt/format conversions on injected strings and the XML value is malformed; setter eagerly connects to a resource (DB/queue) that is down; setter asserts configuration validity and fails on bad process config.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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