flowable/flowable-engine · warning · FlowableOptimisticLockingException
Could not lock process instance
Error message
Could not lock process instance
What it means
updateProcessInstanceLockTime issues a direct SQL update to acquire a process instance lock (used for async job acquisition / exclusive job locking). If the update affects 0 rows, meaning the process instance row no longer matches (deleted, or lock already taken/changed by another node), a FlowableOptimisticLockingException is thrown.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/entity/data/impl/MybatisExecutionDataManager.java:311
@Override
public void updateExecutionTenantIdForDeployment(String deploymentId, String newTenantId) {
HashMap<String, Object> params = new HashMap<>();
params.put("deploymentId", deploymentId);
params.put("tenantId", newTenantId);
getDbSqlSession().directUpdate("updateExecutionTenantIdForDeployment", params);
}
@Override
public void updateProcessInstanceLockTime(String processInstanceId, Date lockDate, String lockOwner, Date expirationTime) {
HashMap<String, Object> params = new HashMap<>();
params.put("id", processInstanceId);
params.put("lockTime", lockDate);
params.put("expirationTime", expirationTime);
params.put("lockOwner", lockOwner);
int result = getDbSqlSession().directUpdate("updateProcessInstanceLockTime", params);
if (result == 0) {
throw new FlowableOptimisticLockingException("Could not lock process instance");
}
}
@Override
public void updateAllExecutionRelatedEntityCountFlags(boolean newValue) {
getDbSqlSession().directUpdate("updateExecutionRelatedEntityCountEnabled", newValue);
}
@Override
public void clearProcessInstanceLockTime(String processInstanceId) {
HashMap<String, Object> params = new HashMap<>();
params.put("id", processInstanceId);
getDbSqlSession().directUpdate("clearProcessInstanceLockTime", params);
}
@Override
public void clearAllProcessInstanceLockTimes(String lockOwner) {
HashMap<String, Object> params = new HashMap<>();View on GitHub (pinned to d6d39ce1c6)
Solutions
- Retry the operation — this is an optimistic-locking conflict; the async executor normally retries automatically, so in custom code wrap the command in a retry with backoff.
- Ensure async executor configuration (exclusive lock settings, asyncExecutorActivate) matches a single or properly clustered setup.
- Verify the process instance still exists before locking and handle the case where it completed concurrently.
- Check that all engine nodes use the same database and consistent lock timeout configuration.
Example fix
// before
managementService.executeCommand(new LockProcessInstanceCmd(instanceId, owner, duration)); // throws on conflict
// after
int attempts = 3;
while (attempts-- > 0) {
try { managementService.executeCommand(cmd); break; }
catch (FlowableOptimisticLockingException e) { /* backoff and retry */ }
} Defensive patterns
Strategy: retry
Validate before calling
boolean exists = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).count() > 0; if (!exists) return; // instance already gone; skip lock
Try / catch
try { /* acquire lock */ } catch (FlowableOptimisticLockingException e) { Thread.sleep(backoff); retry(); } Prevention
- Use retry with backoff for lock acquisition in clustered setups
- Keep async executor configuration consistent across nodes
- Verify instance existence before locking
- Don't hold instance locks longer than the expiration window
When it happens
Trigger: Async executor acquiring/locking a process instance lock where the ACT_RU_EXECUTION row was deleted or its lock columns changed between read and update; concurrent job acquisition on multiple engine nodes competing for the same instance lock.
Common situations: Clustered Flowable deployments with multiple async executors racing on the same process instance; process instance finishing/being deleted while a lock was being acquired; lock expiration time changed by another thread.
Related errors
- Could not lock case instance
- ${updatedObject} was updated by another transaction concurre
- ${entity} was updated by another transaction concurrently
- <persistentObject> was updated by another transaction concur
- One of the entities <persistentObjectClass> was updated by a
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/27885da7a65719b2.
Report an issue: GitHub.