Activiti/Activiti · error · ActivitiException
Entity does not exist
Error message
Entity does not exist: ${entityClass.getName()} - ${primaryKey} What it means
findEntity resolves a stored JPA variable back into a live entity by calling EntityManager.find(entityClass, primaryKey). If the persistence provider returns null — no row with that primary key exists — Activiti throws ActivitiException 'Entity does not exist: <class> - <pk>'. The variable references an entity that has been deleted or never existed in the database.
Solutions
- Recreate/restore the missing row with the stored primary key.
- Fix referential hygiene: prevent deletion of entities referenced by running process variables (FK constraints or soft-delete).
- Verify the persistence unit/datasource points at the same database the variable was created against.
Example fix
// before
customerRepository.delete(customer); // row referenced by running process
// after
// soft delete or verify no active process variables reference the entity first
if (!hasActiveProcessReferences(customer.getId())) {
customerRepository.delete(customer);
} Defensive patterns
Strategy: try-catch
Validate before calling
// before relying on the variable, check the row still exists
Object pk = /* stored primary key */;
Object entity = entityManager.find(Order.class, pk);
if (entity == null) {
logger.warn("Order " + pk + " no longer exists; handle or fail the process step");
} Try / catch
try {
Order order = (Order) runtimeService.getVariable(executionId, "order");
} catch (ActivitiException e) {
if (e.getMessage().startsWith("Entity does not exist")) {
logger.warn("Referenced entity deleted; compensating...");
// take alternate path or restore the row
} else { throw e; }
} Prevention
- Prevent deletion of entities referenced by running processes (FK constraints, soft-delete)
- Keep engine datasource and persistence unit pointed at the same DB
- Archive entity data together with process data
When it happens
Trigger: Deserializing a JPA process variable whose stored primary key no longer matches any DB row, e.g. during process execution after the referenced row was deleted, or with a variable saved against a different database/environment than the one currently configured.
Common situations: Entity rows purged by cleanup jobs or cascading deletes while processes referencing them still run; pointing the engine at a different schema/test DB that lacks the row; restoring process data without restoring entity data.
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
- Cannot find field or method with annotation @Id on class
- Error while flushing EntityManager
- Unsupported Primary key type for JPA-Entity
- Unsupported Primary key type for JPA-Entity
- Value of primary key for JPA-Entity cannot be null
AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09).
Data as JSON: /api/errors/b1ddf95d851dbe02.
Report an issue: GitHub.
Appendix: source
Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/variable/JPAEntityMappings.java:138
}
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 ActivitiException("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 56435b1a97)