flowable/flowable-engine · error · ActivitiException
no delete statement for <persistentObjectClass> in the ibati
Error message
no delete statement for <persistentObjectClass> in the ibatis mapping files
What it means
Thrown by DbSqlSession's delete operation as ActivitiException when the DbSqlSessionFactory returns no 'delete' statement mapped for the persistent object's class in the iBATIS/MyBatis mapping files. Every persistable entity must have a mapped delete statement; a missing mapping means the class is not a recognized persistable entity.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/db/DbSqlSession.java:233
}
@Override
public boolean sameIdentity(PersistentObject other) {
return persistentObject.getClass().equals(other.getClass())
&& persistentObject.getId().equals(other.getId());
}
@Override
public void clearCache() {
cacheRemove(persistentObject.getClass(), persistentObject.getId());
}
@Override
public void execute() {
String deleteStatement = dbSqlSessionFactory.getDeleteStatement(persistentObject.getClass());
deleteStatement = dbSqlSessionFactory.mapStatement(deleteStatement);
if (deleteStatement == null) {
throw new ActivitiException("no delete statement for " + persistentObject.getClass() + " in the ibatis mapping files");
}
// It only makes sense to check for optimistic locking exceptions for objects that actually have a revision
if (persistentObject instanceof HasRevision) {
int nrOfRowsDeleted = sqlSession.delete(deleteStatement, persistentObject);
if (nrOfRowsDeleted == 0) {
throw new ActivitiOptimisticLockingException(persistentObject + " was updated by another transaction concurrently");
}
} else {
sqlSession.delete(deleteStatement, persistentObject);
}
}
public PersistentObject getPersistentObject() {
return persistentObject;
}
@OverrideView on GitHub (pinned to d6d39ce1c6)
Solutions
- Use the proper service API for deletion (e.g. managementService.deleteJob, taskService.deleteTask) instead of generic PersistentObject deletion.
- If deleting a custom entity, add a delete<ShortClassName> statement to the MyBatis mapping XML and register it via dbSqlSessionFactory.getDeleteStatements()/statementMappings.
- Verify engine jar versions are consistent — all Flowable/Activiti modules on the same version so mappings and classes match.
- Ensure you pass the actual entity class, not a subclass/DTO, to the delete path.
Example fix
// before
commandContext.getDbSqlSession().delete(myCustomDto); // no mapping for DTO class
// after
MyCustomEntity entity = commandContext.getDbSqlSession()
.selectById(MyCustomEntity.class, id); // mapped entity with deleteMyCustomEntity statement
commandContext.getDbSqlSession().delete(entity); Defensive patterns
Strategy: validation
Validate before calling
if (!(obj instanceof KnownActivitiEntity)) {
throw new IllegalArgumentException(
"Class " + obj.getClass() + " has no engine delete mapping; use a mapped entity");
} Type guard
boolean hasDeleteMapping(Object persistentObject) {
return persistentObject instanceof Entity; // engine-mapped persistable entities
} Try / catch
try {
dbSqlSession.delete(persistentObject);
} catch (ActivitiException e) {
if (e.getMessage() != null && e.getMessage().startsWith("no delete statement for")) {
throw new PersistenceMappingException(persistentObject.getClass(), e);
}
throw e;
} Prevention
- Only pass engine entities (Entity implementors) to generic delete paths
- For custom entities, always ship both mapping XML and DbSqlSessionFactory statement registration
- Keep all engine module versions aligned so classes and mappings match
- Prefer service-level delete APIs over raw DbSqlSession access
When it happens
Trigger: Calling persistence APIs (e.g. managementService.executeCommand deleting a PersistentObject) for a custom or unrecognized entity class without registering a delete statement; deleting a stale/foreign entity class through the generic dbSqlSession.executeDelete; engine jar/version mismatch where entity classes exist without matching mappings.
Common situations: Custom entities added to the engine without corresponding MyBatis XML mapping and insert/delete registration in DbSqlSessionFactory; mixing engine jar versions where a class's mapping file changed names; passing the wrong object (e.g. a DTO) to a delete path.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- no insert statement for ${entities.iterator().next().getClas
- no update statement for ${updatedObject.getClass()} in the i
- no delete statement for ${entity.getClass()} in the ibatis m
- no insert statement for ${entity.getClass()} in the ibatis m
- couldn't get table counts
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/fd6546f043479d2a.
Report an issue: GitHub.