flowable/flowable-engine · error · FlowableIllegalArgumentException

Field definition uses non-existing field '<fieldName>' on cl

Error message

Field definition uses non-existing field '<fieldName>' on class <className>

What it means

Thrown by ClassDelegateUtil.applyFieldDeclaration as a FlowableIllegalArgumentException when the field declaration's name does not match any field on the target delegate class (ReflectUtil.getField returns null). It means the BPMN field injection references a property that does not exist on the delegate.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/ClassDelegateUtil.java:64

    }

    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());
        } else {
            // Null can be set any field type
            return true;
        }
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Correct the field name in the BPMN XML to match an existing field or setter on the delegate class
  2. Add the missing field (with public setter) to the delegate class
  3. Verify the class/delegateExpression on the service task points at the intended class
  4. Search the process definitions for all <flowable:field> names and validate against delegate sources at build time

Example fix

// before
<flowable:field name="timeOut" stringValue="10"/>
// after (delegate has field 'timeout')
<flowable:field name="timeout" stringValue="10"/>
Defensive patterns

Strategy: validation

Validate before calling

// Validate BPMN field names against delegate fields before deployment
Set<String> available = ReflectUtil.getFields(delegateClass).keySet();
if (!available.contains(declaredFieldName)) {
    throw new DeploymentException("Field " + declaredFieldName + " missing on " + delegateClass.getName());
}

Type guard

static boolean delegateHasField(Class<?> delegate, String name) {
    try { delegate.getDeclaredField(name); return true; }
    catch (NoSuchFieldException e) { return false; }
}

Try / catch

try { deploy(processDefinition); }
catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("non-existing field")) {
        log.error("BPMN references missing delegate field: {}", e.getMessage());
    } else throw e;
}

Prevention

When it happens

Trigger: <flowable:field name="..."> in the process definition names a field/setter that is absent on the class instantiated for the service task, so applyFieldDeclaration fails after the setter lookup falls through to ReflectUtil.getField.

Common situations: Typo in the field name in BPMN XML; refactored/renamed delegate field without updating the process definition; wrong delegateExpression/class pointing at a class without that field; copying process XML between projects.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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