flowable/flowable-engine · error · FlowableIllegalArgumentException

Incompatible type set on field declaration '${name}' for cla

Error message

Incompatible type set on field declaration '${name}' for class ${target.getClass().getName()}. Declared value has type ${value.getClass().getName()}, while expecting ${field.getType().getName()}

What it means

After locating the target field, invokeSetterOrField checks that the value's type is assignable to the field's declared type via fieldTypeCompatible. If not, it throws this FlowableIllegalArgumentException detailing the value type and the expected field type.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/util/ReflectUtil.java:181

    public static void invokeSetterOrField(Object target, String name, Object value, boolean throwExceptionOnMissingField) {
        Method setterMethod = getSetter(name, target.getClass(), value.getClass());

        if (setterMethod != null) {
            invokeSetter(setterMethod, target, name, value);
            
        } else {
            Field field = ReflectUtil.getField(name, target);
            if (field == null) {
                if (throwExceptionOnMissingField) {
                    throw new FlowableIllegalArgumentException("Field definition uses non-existent field '" + name + "' of class " + target.getClass().getName());
                } else {
                    return;
                }
            }

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

    /**
     * Returns the field of the given object or null if it doesn't 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 doesn't exist.

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Align the field's declared type with the injected value type (e.g. change String field to int, or inject a String value).
  2. In BPMN XML, set the correct type attribute on <flowable:field>/<flowable:value> (e.g. stringValue, expression).
  3. For numeric fields, ensure the value resolves to the numeric type, or accept a String and parse it inside the delegate.
  4. Update the process definition after refactoring field types.
  5. Check both the value.getClass() and expected type printed in the message to pinpoint the mismatch.

Example fix

// before
private int retryLimit; // injected with <flowable:string value="10"/>
// after
<flowable:field name="retryLimit"><flowable:value>10</flowable:value></flowable:field> <!-- numeric injection -->
// or change field to String and parse
Defensive patterns

Strategy: validation

Validate before calling

Field f = target.getClass().getDeclaredField(name);
if (!f.getType().isAssignableFrom(value.getClass())
    && !(f.getType().isPrimitive() && isCompatiblePrimitive(f.getType(), value.getClass())))
    throw new IllegalStateException("Value " + value.getClass() + " not assignable to " + f.getType());

Try / catch

try {
    ReflectUtil.invokeSetterOrField(target, name, value, true);
} catch (FlowableIllegalArgumentException e) {
    LOGGER.error("Field {} type mismatch: {}", name, e.getMessage());
    throw new IllegalArgumentException("Fix injected value type for field " + name, e);
}

Prevention

When it happens

Trigger: Injecting a value whose runtime type does not match the declared field type — e.g. a String field injection into an int/long field, a String into a custom bean field, or an expression that resolves to a different type than the field expects, in flowable:field definitions.

Common situations: BPMN field injection where the delegate declares int/boolean but the XML value is a string without the right type attribute; expression evaluating to the wrong type; changed field type after refactor.

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/880b263c2c283ed9. Report an issue: GitHub.