flowable/flowable-engine · error · FlowableException
Cannot find field or method with annotation @Id on class '${
Error message
Cannot find field or method with annotation @Id on class '${class}', only single-valued primary keys are supported on JPA-entities What it means
JPAEntityScanner inspects a JPA entity class and its superclasses to locate the primary key, supporting only a single @Id-annotated field or getter. If neither exists (e.g. composite @EmbeddedId, @IdClass, or missing annotations), it throws this FlowableException.
Source
Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/types/JPAEntityScanner.java:53
while (clazz != null && !clazz.equals(Object.class)) {
// Class should have @Entity annotation
boolean isEntity = isEntityAnnotationPresent(clazz);
if (isEntity) {
metaData.setEntityClass(clazz);
metaData.setJPAEntity(true);
// Try to find a field annotated with @Id
Field idField = getIdField(clazz);
if (idField != null) {
metaData.setIdField(idField);
} else {
// Try to find a method annotated with @Id
Method idMethod = getIdMethod(clazz);
if (idMethod != null) {
metaData.setIdMethod(idMethod);
} else {
throw new FlowableException("Cannot find field or method with annotation @Id on class '" + clazz.getName() + "', only single-valued primary keys are supported on JPA-entities");
}
}
break;
}
clazz = clazz.getSuperclass();
}
return metaData;
}
private Method getIdMethod(Class<?> clazz) {
Method idMethod = null;
// Get all public declared methods on the class. According to spec, @Id should only be
// applied to fields and property get methods
Method[] methods = clazz.getMethods();
Id idAnnotation = null;
for (Method method : methods) {
idAnnotation = method.getAnnotation(Id.class);
if (idAnnotation != null && !method.isBridge()) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Give the entity a single @Id-annotated field or getter (annotations, not XML mapping — the scanner reads reflection annotations).
- Replace composite keys (@EmbeddedId/@IdClass) with a single-valued synthetic key (e.g. String or Long surrogate key) if the entity must be used as a Flowable variable.
- If you must keep the composite key, wrap the lookup in your own variable type or store the individual key columns as separate variables.
- Upgrade check: confirm the class hierarchy chain — @Id must be on the class or a superclass reachable via getSuperclass(), not on an @MappedSuperclass outside the chain you expect.
Example fix
// before @EmbeddedId private CustomerPk id; // composite -> throws // after @Id @GeneratedValue private Long id; // single-valued key
Defensive patterns
Strategy: validation
Validate before calling
for (Class<?> c = entityClass; c != null; c = c.getSuperclass()) {
boolean hasId = Arrays.stream(c.getDeclaredFields()).anyMatch(f -> f.isAnnotationPresent(jakarta.persistence.Id.class))
|| Arrays.stream(c.getDeclaredMethods()).anyMatch(m -> m.isAnnotationPresent(jakarta.persistence.Id.class));
if (hasId) return;
}
throw new IllegalArgumentException(entityClass + " has no single @Id field/getter"); Type guard
boolean scannableEntity(Class<?> c) { return c.isAnnotationPresent(jakarta.persistence.Entity.class) && singleIdAnnotationCount(c) == 1; } Try / catch
try { runtimeService.setVariable(executionId, "entity", jpaEntity); } catch (FlowableException e) { if (e.getMessage().contains("Cannot find field or method with annotation @Id")) { throw new ConfigurationException("Use single-valued @Id entities with Flowable JPA variables", e); } throw e; } Prevention
- Never use @EmbeddedId or @IdClass entities as Flowable JPA variables — use a surrogate single-valued key.
- Rely on annotation-based mapping (not pure orm.xml) since the scanner uses reflection annotations.
- Add a startup test that scans all entities eligible for variables for exactly one @Id member.
When it happens
Trigger: First time a JPA entity class is used as a Flowable variable: scanClass finds no @Id field and no @Id getter anywhere in the class hierarchy — entities with @EmbeddedId/@IdClass composite keys, or entities annotated only with e.g. @GeneratedValue without @Id.
Common situations: Composite primary key entities (very common in legacy schemas); entities relying on XML ORM mapping instead of annotations; typo where the getter lost its @Id annotation during refactoring.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported Primary key type for JPA-Entity: ${type}
- Value of primary key for JPA-Entity cannot be null
- Cannot get id from JPA Entity, no id method/field set
- Unsupported Primary key type for JPA-Entity:
- JPA entity variables can only be used in 'variableValueEqual
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/41da40a269b394cc.
Report an issue: GitHub.