flowable/flowable-engine · error · ActivitiException
no update statement for <updatedObjectClass> in the ibatis m
Error message
no update statement for <updatedObjectClass> in the ibatis mapping files
What it means
flushUpdates() resolves the update statement for each dirty persistent object via dbSqlSessionFactory.getUpdateStatement(updatedObject) and mapStatement(). A null result means no update statement is mapped for that class in the iBatis/MyBatis mapping files, and the flush throws this ActivitiException. This is a mapping-configuration error for the update path of the entity.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/db/DbSqlSession.java:825
}
if (persistentObjectList.get(0) instanceof HasRevision) {
for (PersistentObject insertedObject : persistentObjectList) {
HasRevision revisionEntity = (HasRevision) insertedObject;
if (revisionEntity.getRevision() == 0) {
revisionEntity.setRevision(revisionEntity.getRevisionNext());
}
}
}
}
protected void flushUpdates(List<PersistentObject> updatedObjects) {
for (PersistentObject updatedObject : updatedObjects) {
String updateStatement = dbSqlSessionFactory.getUpdateStatement(updatedObject);
updateStatement = dbSqlSessionFactory.mapStatement(updateStatement);
if (updateStatement == null) {
throw new ActivitiException("no update statement for " + updatedObject.getClass() + " in the ibatis mapping files");
}
LOGGER.debug("updating: {}", updatedObject);
int updatedRecords = sqlSession.update(updateStatement, updatedObject);
if (updatedRecords != 1) {
throw new ActivitiOptimisticLockingException(updatedObject + " was updated by another transaction concurrently");
}
// See https://activiti.atlassian.net/browse/ACT-1290
if (updatedObject instanceof HasRevision) {
((HasRevision) updatedObject).setRevision(((HasRevision) updatedObject).getRevisionNext());
}
}
updatedObjects.clear();
}
protected void flushDeletes(List<DeleteOperation> removedOperations) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Add the <update> mapped statement with the id expected by getUpdateStatement (including optimistic-locking REV_ = REV_ + 1 predicate) to the entity's mapping XML and load it in the configuration.
- Audit the mapping file for the entity to ensure insert, update, and delete statements all exist with conventional ids.
- If the object should never be updated, exclude it from the persistence cache or mark it non-dirty rather than letting flushUpdates process it.
Example fix
// before: XML has insert/select only
// after
<update id="updateCustomEntity" parameterType="org.example.CustomEntityEntityImpl">
UPDATE ACT_CUSTOM_ENTITY SET NAME_ = #{name}, REV_ = #{revisionNext} WHERE ID_ = #{id} AND REV_ = #{revision}
</update> Defensive patterns
Strategy: validation
Validate before calling
// Verify update mapping exists before making the entity dirty
String stmt = dbSqlSessionFactory.getUpdateStatement(entity);
if (stmt == null || dbSqlSessionFactory.mapStatement(stmt) == null) {
throw new IllegalStateException("No update statement mapped for " + entity.getClass().getName());
} Try / catch
try {
runtimeService.setVariable(executionId, "k", v); // may flush updates
} catch (ActivitiException e) {
if (e.getMessage().contains("no update statement")) {
throw new ConfigurationException("Update mapping missing for custom entity", e);
}
throw e;
} Prevention
- Author update statements (with REV_ optimistic-lock predicate) for all custom entities.
- Audit mapping XMLs so insert/update/delete exist together for each entity.
- Add a CI test that creates, mutates, and saves each custom entity to exercise the update path.
When it happens
Trigger: A PersistentObject becomes dirty during a command and flushUpdates runs; the class has no <update> statement id matching what getUpdateStatement returns, or its mapping XML is not loaded into the engine configuration.
Common situations: Custom entities registered as updateable without an update mapping; refactoring that renamed the statement id; partial mapping files where insert/select exist but update was omitted.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- no bulk delete statement for <persistentObjectClass> in the
- no insert statement for <persistentObjectClass> in the ibati
- no insert statement for ${entity.getClass()} in the ibatis m
- JDBC requires that the JdbcType must be specified for all nu
- Error setting null for parameter #${i} with JdbcType ${jdbcT
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/95b7b4f1742fc777.
Report an issue: GitHub.