flowable/flowable-engine · error · FlowableException

Illegal argument exception when getting value from id method

Error message

Illegal argument exception when getting value from id method/field on JPAEntity

What it means

Flowable's JPA variable type reads the primary key of a JPA entity variable via reflection, invoking the configured @Id getter method or reading the @Id field. A java.lang.IllegalArgumentException from Method.invoke or Field.get means the object being passed is not an instance of the class that declares that id method/field, or the value cannot be converted to the declared parameter/return type. Flowable wraps it in a FlowableException with this message.

Source

Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/types/JPAEntityMappings.java:98

    public String getJPAIdString(Object value) {
        EntityMetaData metaData = getEntityMetaData(value.getClass());
        if (!metaData.isJPAEntity()) {
            throw new FlowableIllegalArgumentException("Object is not a JPA Entity: class='" + value.getClass() + "', " + value);
        }
        Object idValue = getIdValue(value, metaData);
        return getIdString(idValue);
    }

    public Object getIdValue(Object value, EntityMetaData metaData) {
        try {
            if (metaData.getIdMethod() != null) {
                return metaData.getIdMethod().invoke(value);
            } else if (metaData.getIdField() != null) {
                return metaData.getIdField().get(value);
            }
        } catch (IllegalArgumentException iae) {
            throw new FlowableException("Illegal argument exception when getting value from id method/field on JPAEntity", iae);
        } catch (IllegalAccessException iae) {
            throw new FlowableException("Cannot access id method/field for JPA Entity", iae);
        } catch (InvocationTargetException ite) {
            throw new FlowableException("Exception occurred while getting value from id field/method on JPAEntity: " + ite.getCause().getMessage(), ite.getCause());
        }

        // Fall trough when no method and field is set
        throw new FlowableException("Cannot get id from JPA Entity, no id method/field set");
    }

    public Object getJPAEntity(String className, String idString) {
        Class<?> entityClass = null;
        entityClass = ReflectUtil.loadClass(className);

        EntityMetaData metaData = getEntityMetaData(entityClass);

        // Create primary key of right type
        Object primaryKey = createId(metaData, idString);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the object stored as a JPA variable is an actual instance of the entity class listed in configuration <jpa-persistence-unit> / jpaEntityClassMappings (check value.getClass() vs metaData target class).
  2. Ensure the @Id accessor has no unexpected parameter types and the entity class is not shadowed by duplicate class versions on the classpath.
  3. Disable or unwrap lazy proxies before persisting the variable, or configure the id method on the concrete entity class.
  4. Call Flowable's refresh on EntityMetaData (scanEntities) after changing entity classes so cached metadata matches runtime classes.

Example fix

// before
entityManager.find(Order.class, id); // proxy instance of subclass stored
variableScope.setVariable("order", order.getLazyProxy());
// after
Order order = entityManager.find(Order.class, id); // concrete instance
variableScope.setVariable("order", order);
Defensive patterns

Strategy: type-guard

Validate before calling

// before storing/reading a JPA variable
if (value == null || !expectedEntityClass.isInstance(value)) {
    throw new IllegalArgumentException("Value is not an instance of " + expectedEntityClass.getName());
}

Type guard

boolean isJpaEntityOfType(Object v, Class<?> entityType) {
    return v != null && entityType.isAssignableFrom(v.getClass()) && !v.getClass().getName().contains("$Proxy");
}

Try / catch

try {
    Object id = variableScope.getVariable("entityVar");
} catch (org.flowable.common.engine.api.FlowableException e) {
    if (e.getCause() instanceof IllegalArgumentException) {
        // re-fetch or unwrap proxy, then retry
    }
}

Prevention

When it happens

Trigger: Calling idValue()/getIdValue() with a 'value' object that is not an instance of the entity class the EntityMetaData was built from (e.g. a proxy, a different entity type, or null-typed mismatch), or a getter whose declared parameter/return type is incompatible with the supplied argument during Method.invoke.

Common situations: Storing a variable whose runtime type differs from the entity class registered in the VariableServiceConfiguration JPA entity list; using Hibernate/javassist lazy-loading proxies passed to the reflective accessor; mismatched entity class after refactoring; storing a JPA variable when jpaHandleTransaction/persistence unit was misconfigured so the object is not the real entity.

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


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