flowable/flowable-engine · error · FlowableException
Exception while invoking '<fieldName>' on class <className>
Error message
Exception while invoking '<fieldName>' on class <className>
What it means
Thrown by ClassDelegateUtil.applyFieldDeclaration when the reflective setter call throws an InvocationTargetException, i.e. the invoked setter itself raised an exception internally. Flowable wraps it in a FlowableException naming the field and target class; the root cause is in the wrapped exception.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/ClassDelegateUtil.java:59
if (fieldDeclarations != null) {
for (FieldDeclaration declaration : fieldDeclarations) {
applyFieldDeclaration(declaration, target);
}
}
}
public static void applyFieldDeclaration(FieldDeclaration declaration, Object target) {
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 FlowableException("Error while invoking '" + declaration.getName() + "' on class " + target.getClass().getName(), e);
} catch (IllegalAccessException e) {
throw new FlowableException("Illegal access when calling '" + declaration.getName() + "' on class " + target.getClass().getName(), e);
} catch (InvocationTargetException e) {
throw new FlowableException("Exception while invoking '" + declaration.getName() + "' on class " + target.getClass().getName(), e);
}
} else {
Field field = ReflectUtil.getField(declaration.getName(), target);
if (field == null) {
throw new FlowableIllegalArgumentException("Field definition uses non-existing field '" + declaration.getName() + "' on class " + target.getClass().getName());
}
// Check if the delegate field's type is correct
if (!fieldTypeCompatible(declaration, field)) {
throw new FlowableIllegalArgumentException("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());
}
ReflectUtil.setField(field, target, declaration.getValue());
}
}
public static boolean fieldTypeCompatible(FieldDeclaration declaration, Field field) {
if (declaration.getValue() != null) {
return field.getType().isAssignableFrom(declaration.getValue().getClass());View on GitHub (pinned to d6d39ce1c6)
Solutions
- Inspect the wrapped InvocationTargetException cause in the stack trace to find the real failure inside the setter
- Fix the throwing logic in the setter of the delegate class
- Correct the field value/expression in the BPMN XML so the setter accepts it
- Add validation of injected values before assignment in the setter with a descriptive message
Example fix
// before
public void setTimeout(String t) { this.timeout = Integer.parseInt(t); }
// after
public void setTimeout(String t) {
try { this.timeout = Integer.parseInt(t); }
catch (NumberFormatException e) { throw new IllegalArgumentException("timeout must be a number, got: " + t, e); }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Smoke-instantiate and invoke the setter with the declared value before deployment
Object d = delegateClass.getDeclaredConstructor().newInstance();
delegateClass.getMethod("set" + cap(field), String.class).invoke(d, declaredValue); Type guard
static boolean setterSafe(Object target, String field, Object value) {
try { target.getClass().getMethod("set" + cap(field)).invoke(target, value); return true; }
catch (Exception e) { return false; }
} Try / catch
try { runtimeService.startProcessInstanceByKey(key); }
catch (FlowableException e) {
if (e.getCause() instanceof InvocationTargetException) {
Throwable root = e.getCause().getCause();
log.error("Setter for {} failed: {}", e.getMessage(), root, root);
} else throw e;
} Prevention
- Keep setters trivial (assign-only); do parsing/validation elsewhere
- Unit test every delegate with its declared field values
- Log the full cause chain, the real error is inside InvocationTargetException
When it happens
Trigger: A BPMN field injection resolves to a setter that executes and throws (e.g. IllegalArgumentException from parsing, NullPointerException inside the setter body) while applyFieldDeclaration runs setterMethod.invoke(target, declaration.getValue()).
Common situations: Setter performs validation or parsing of the injected string/expression value and rejects it; injected expression evaluates to an unexpected value; constructor-time state missing when setter runs.
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
- Field definition uses non-existent field '${name}' of class
- Incompatible type set on field declaration '${name}' for cla
- Could not set field ${field}
- Illegal access when calling '<fieldName>' on class <classNam
- Exception while invoking '%s' on class %s
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/505c510adae64bcf.
Report an issue: GitHub.