flowable/flowable-engine · error · FlowableException
Entity does not exist: ${entityClass} - ${primaryKey}
Error message
Entity does not exist: ${entityClass} - ${primaryKey} What it means
When deserializing a JPA entity variable from storage, Flowable loads the entity via EntityManager.find(entityClass, primaryKey). If the find returns null — no row exists for that primary key — Flowable throws this FlowableException naming the entity class and key.
Source
Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/types/JPAEntityMappings.java:125
}
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);
return findEntity(entityClass, primaryKey);
}
private Object findEntity(Class<?> entityClass, Object primaryKey) {
EntityManager em = Context.getCommandContext().getSession(EntityManagerSession.class).getEntityManager();
Object entity = em.find(entityClass, primaryKey);
if (entity == null) {
throw new FlowableException("Entity does not exist: " + entityClass.getName() + " - " + primaryKey);
}
return entity;
}
public Object createId(EntityMetaData metaData, String string) {
Class<?> type = metaData.getIdType();
// According to JPA-spec all primitive types (and wrappers) are
// supported, String, util.Date, sql.Date,
// BigDecimal and BigInteger
if (type == Long.class || type == long.class) {
return Long.parseLong(string);
} else if (type == String.class) {
return string;
} else if (type == Byte.class || type == byte.class) {
return Byte.parseByte(string);
} else if (type == Short.class || type == short.class) {
return Short.parseShort(string);
} else if (type == Integer.class || type == int.class) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Restore the missing row or correct the database the engine is pointed at (verify persistence unit/DataSource matches the data that created the variable).
- Check the id string-to-type conversion in createId(): the parsed key (e.g. Long.parseLong) must match the @Id column type and value.
- Delete or fix stale variables referencing removed entities; add cleanup of process instances when their referenced entities are deleted.
- Guard application code: catch FlowableException around variable retrieval (getVariable of a JPA type) and handle a missing entity explicitly.
Example fix
// before Order order = (Order) taskService.getVariable(taskId, "order"); // throws if row deleted // after Object v = taskService.getVariable(taskId, "order"); Order order = (v instanceof Order) ? (Order) v : orderRepository.findFallback(taskId);
Defensive patterns
Strategy: try-catch
Validate before calling
// verify the referenced entity exists before relying on the variable Object key = taskService.getVariable(taskId, "orderId"); boolean exists = key != null && entityManager.find(Order.class, key) != null;
Type guard
boolean entityExists(EntityManager em, Class<?> type, Object pk) {
return pk != null && em.find(type, pk) != null;
} Try / catch
try {
Object v = runtimeService.getVariable(executionId, "jpaVar");
} catch (org.flowable.common.engine.api.FlowableException e) {
if (e.getMessage().startsWith("Entity does not exist")) {
// handle deleted entity: re-create, reassign variable, or complete/terminate the process
}
} Prevention
- Never hard-delete entity rows referenced by in-flight process variables; use soft deletes.
- Enable FK constraints or periodic consistency checks between variables and entity tables.
- Ensure id type used in createId matches the @Id column type exactly.
- Point the engine at the same database/environment where the variables were created.
When it happens
Trigger: findEntity() called from getJPAEntity(className, idString): the stored variable references an entity whose row was deleted from the database, or the primary key string was converted to a value that no longer matches any row (wrong createId type, e.g. Long vs String mismatch).
Common situations: Referential integrity without FK constraints: process variables outlive the entity rows; data purged by cleanup jobs or cascading deletes while the process instance still holds a JPA variable; running against a different database/environment than the one the variable was created in; id type conversion (createId) producing a differently-typed key that finds nothing.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Entity does not exist: -
- No decision table found with id ${decisionTableId}
- Lock with name ${lockName} does not exist
- The length of the ${variableType.getTypeName()} value exceed
- Error while flushing EntityManager:
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/4e04b12ff7065d2a.
Report an issue: GitHub.