flowable/flowable-engine · error · FlowableException
Could not set field ${field}
Error message
Could not set field ${field} What it means
ReflectUtil.setField makes the field accessible and assigns the value. If the JVM rejects the access (IllegalAccessException) or the value's type is not compatible with the field (IllegalArgumentException from Field.set), the failure is wrapped in this FlowableException.
Source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/util/ReflectUtil.java:223
} catch (SecurityException e) {
throw new FlowableException("not allowed to access field " + field + " on class " + clazz.getCanonicalName(), e);
} catch (NoSuchFieldException e) {
// for some reason getDeclaredFields doesn't search superclasses
// (which getFields() does ... but that gives only public fields)
Class<?> superClass = clazz.getSuperclass();
if (superClass != null) {
return getField(fieldName, superClass);
}
}
return field;
}
public static void setField(Field field, Object object, Object value) {
try {
field.setAccessible(true);
field.set(object, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new FlowableException("Could not set field " + field, e);
}
}
/**
* Returns the setter-method for the given field name or null if no setter exists.
*/
public static Method getSetter(String fieldName, Class<?> clazz, Class<?> fieldType) {
String setterName = "set" + Character.toTitleCase(fieldName.charAt(0)) + fieldName.substring(1);
try {
// Using getMethods(), getMethod(...) expects exact parameter type
// matching and ignores inheritance-tree.
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.getName().equals(setterName)) {
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes != null && paramTypes.length == 1 && paramTypes[0].isAssignableFrom(fieldType)) {
return method;
}View on GitHub (pinned to d6d39ce1c6)
Solutions
- Check the cause: IllegalArgumentException → value type incompatible; ensure the value matches the field type (and is non-null for primitives).
- Verify the field is not final/static in a way that blocks setting (Field.set on final fields may still fail depending on JDK).
- Add --add-opens if the field's package is encapsulated by the module system.
- Fix the value passed by the caller (e.g. convert String to int before injection).
- Prefer a setter method over raw field reflection when possible.
Example fix
// before ReflectUtil.setField(retriesField, delegate, null); // int field // after ReflectUtil.setField(retriesField, delegate, 3);
Defensive patterns
Strategy: type-guard
Validate before calling
if (value == null && field.getType().isPrimitive())
throw new IllegalStateException("Cannot set null on primitive field " + field.getName());
if (value != null && !field.getType().isAssignableFrom(value.getClass()))
throw new IllegalStateException("Value type " + value.getClass() + " not assignable to " + field.getType()); Type guard
static boolean isSettable(Field f, Object v) {
if (v == null) return !f.getType().isPrimitive();
Class<?> boxed = f.getType().isPrimitive()
? Map.of(int.class, Integer.class, long.class, Long.class, boolean.class, Boolean.class,
double.class, Double.class, float.class, Float.class, short.class, Short.class,
byte.class, Byte.class, char.class, Character.class).getOrDefault(f.getType(), f.getType())
: f.getType();
return boxed.isAssignableFrom(v.getClass());
} Try / catch
try {
ReflectUtil.setField(field, object, value);
} catch (FlowableException e) {
LOGGER.error("Set field {} failed: {}", field, e.getCause().getMessage());
throw new IllegalArgumentException("Incompatible value for field " + field.getName(), e);
} Prevention
- Never pass null for primitive fields
- Coerce value types (String→int, etc.) before reflective assignment
- Avoid final and module-encapsulated fields
- Prefer setters or constructor injection over raw field reflection
When it happens
Trigger: Calling setField(field, object, value) where value's runtime type is not assignable to the field's declared type (e.g. null into a primitive field, wrong object type), or a security/module boundary blocks setAccessible despite it appearing to succeed.
Common situations: Field injection in Flowable where expression values resolve to unexpected types; setting null on primitive fields; reflecting into final/static or module-encapsulated fields; JDK upgrades adding module restrictions.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Incompatible type set on field declaration '${name}' for cla
- Field definition uses non-existent field '${name}' of class
- Illegal access when calling '<fieldName>' on class <classNam
- Exception while invoking '<fieldName>' on class <className>
- Incompatible type set on field declaration '<fieldName>' for
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/2283896f10bc3597.
Report an issue: GitHub.