flowable/flowable-engine · error · ActivitiIllegalArgumentException
Object is not a JPA Entity: class='${value.getClass()}', ${v
Error message
Object is not a JPA Entity: class='${value.getClass()}', ${value} What it means
getJPAClassString validates that the value's class is annotated as a JPA entity (via EntityMetaData.isJPAEntity). If the object lacks @Entity (or valid JPA metadata), it cannot be stored as a JPA entity variable, so this error is thrown.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/JPAEntityMappings.java:76
// Class not present in meta-data map, create metaData for it and add
metaData = scanClass(clazz);
classMetaDatamap.put(clazz.getName(), metaData);
}
return metaData;
}
private EntityMetaData scanClass(Class<?> clazz) {
return enitityScanner.scanClass(clazz);
}
public String getJPAClassString(Object value) {
if (value == null) {
throw new ActivitiIllegalArgumentException("null value cannot be saved");
}
EntityMetaData metaData = getEntityMetaData(value.getClass());
if (!metaData.isJPAEntity()) {
throw new ActivitiIllegalArgumentException("Object is not a JPA Entity: class='" + value.getClass() + "', " + value);
}
// Extract the class from the Entity instance
return metaData.getEntityClass().getName();
}
public String getJPAIdString(Object value) {
EntityMetaData metaData = getEntityMetaData(value.getClass());
if (!metaData.isJPAEntity()) {
throw new ActivitiIllegalArgumentException("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) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Annotate the class with @Entity and ensure it has a valid @Id
- Verify you are storing the actual entity, not a DTO or wrapper
- Check the JPA/persistence configuration so entity scanning sees the class
- If a plain object is intended, do not use the JPA entity variable mapping
Example fix
// before
public class Order { private Long id; ... }
runtimeService.setVariable(executionId, "order", new Order());
// after
@Entity
public class Order { @Id private Long id; ... } Defensive patterns
Strategy: type-guard
Validate before calling
if (!value.getClass().isAnnotationPresent(Entity.class)) {
throw new IllegalArgumentException(value.getClass() + " is not a JPA entity");
} Type guard
boolean isJpaEntity(Object v) {
return v != null && v.getClass().isAnnotationPresent(javax.persistence.Entity.class);
} Try / catch
try {
runtimeService.setVariable(id, "order", value);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().startsWith("Object is not a JPA Entity")) {
// store as serializable instead
runtimeService.setVariable(id, "order", (Serializable) value);
} else { throw e; }
} Prevention
- Annotate all classes stored as JPA variables with @Entity
- Keep DTOs out of JPA-typed variables
- Verify entity scanning configuration after package moves
When it happens
Trigger: Passing a plain POJO, DTO, collection, String, or an un-annotated class to a variable API that resolves to the JPA entity variable type, or an entity whose metadata scanning failed (missing @Entity annotation).
Common situations: Putting a DTO into a process variable while a JPA entity type was expected; forgetting @Entity on the class; entity class from another persistence unit not scanned; proxy classes (Hibernate) wrapping the entity in odd configurations.
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
- EntityManagerFactory must implement 'jakarta.persistence.Ent
- Value is not a list of JPA entities:
- Cannot get id from JPA Entity, no id method/field set
- EntityManagerFactory must implement 'jakarta.persistence.Ent
- Value is not a list of JPA entities: " + value
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/63be6dbf36749f8c.
Report an issue: GitHub.