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

Could not set field

Error message

Could not set field ${field}

What it means

ReflectUtil.setField() wraps IllegalArgumentException from Field.set() in an ActivitiException 'Could not set field <field>'. IllegalArgumentException means the value's type is not assignable to the field's declared type (or object is not an instance of the declaring class). The engine throws because reflective writes fail outside the caller's control.

Solutions

  1. Check the cause IllegalArgumentException for the exact type mismatch
  2. Ensure the value's type matches (or auto-unboxes/boxes to) the field's declared type
  3. Verify you pass the correct object instance of the declaring class
  4. Wrap primitives correctly (Integer for int fields, etc.)

Example fix

// before
ReflectUtil.setField(field, engineConfiguration, "5"); // String into int field
// after
ReflectUtil.setField(field, engineConfiguration, 5);
Defensive patterns

Strategy: type-guard

Validate before calling

// check assignability before setting
if (value != null && !field.getType().isAssignableFrom(value.getClass())) {
  throw new IllegalArgumentException("cannot assign " + value.getClass() + " to " + field.getType());
}

Type guard

boolean settable(Field f, Object value) {
  return value == null || (f.getType().isAssignableFrom(value.getClass()) || isBoxingMatch(f.getType(), value.getClass()));
}

Try / catch

try {
  ReflectUtil.setField(field, object, value);
} catch (ActivitiException e) {
  throw new IllegalStateException("type mismatch writing field " + field.getName(), e);
}

Prevention

When it happens

Trigger: ReflectUtil.setField(field, object, value) is called with a value whose runtime type doesn't match the field's declared type, or with an object that isn't an instance of field.getDeclaringClass().

Common situations: Injecting a String into an int field or a subtype mismatch when wiring engine internals/test doubles; refactoring a field's type without updating the reflective write; passing the wrong target object instance.

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


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

Appendix: source

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

        } catch (SecurityException e) {
            throw new ActivitiException("not allowed to access field " + field + " on class " + clazz.getCanonicalName(), e);
        } catch (NoSuchFieldException e) {
            // for some reason getDeclaredFields doesnt 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 e) {
            throw new ActivitiException("Could not set field " + field, e);
        } catch (IllegalAccessException e) {
            throw new ActivitiException("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();

View on GitHub (pinned to d6d39ce1c6)