flowable/flowable-engine · warning · ActivitiException
Cannot delete job when the job is being executed. Try again…
Error message
Cannot delete job when the job is being executed. Try again later.
What it means
DeleteJobCmd refuses to delete a job whose lockOwner is set, meaning the async job executor's acquisition thread has already acquired the job and it is executing (or about to execute). Deleting it mid-execution could corrupt processing, so the command throws ActivitiException telling the caller to retry later. This is a deliberate concurrency guard, not a bug.
Solutions
- Wait briefly and retry the deletion after the job finishes (poll until lockOwner is null)
- Stop/suspend the job executor (ProcessEngineConfiguration asyncExecutorActive=false) before deleting
- Clear the lock manually by updating ACT_RU_JOB to null out LOCK_OWNER_/LOCK_EXP_TIME_ during maintenance downtime, then delete
- Catch ActivitiException and implement retry with backoff
Example fix
// before
managementService.deleteJob(jobId);
// after
Job job = managementService.createJobQuery().jobId(jobId).singleResult();
if (job != null && job.getLockOwner() == null) {
managementService.deleteJob(jobId);
} else {
// retry later or suspend the job executor first
} Defensive patterns
Strategy: retry
Validate before calling
Job job = managementService.createJobQuery().jobId(jobId).singleResult(); boolean locked = job != null && job.getLockOwner() != null;
Type guard
boolean deletable(Job job) { return job != null && job.getLockOwner() == null; } Try / catch
try {
managementService.deleteJob(jobId);
} catch (ActivitiException e) {
if (e.getMessage().contains("being executed")) { /* schedule retry with backoff */ }
} Prevention
- Check lockOwner before deleting
- Suspend/stop the async job executor for maintenance deletions
- Use retry with backoff rather than immediate re-delete
When it happens
Trigger: Calling ManagementService.deleteJob(jobId) (or similar delete APIs routed through DeleteJobCmd) while the async job executor has acquired the job — i.e. JOB_.LOCK_OWNER_ and LOCK_EXP_TIME_ are set and unexpired.
Common situations: Admin canceling a stuck-looking job while the job executor is actively running it; clustered setups where another node's acquisition thread grabbed the job; deleting a job immediately after triggering an async continuation.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Could not acquire lock " + lockName + ". Current lock…
- does not hold a lock on the requested job
- job is null
- already taking a transition
- Can only enable a plan item instance which is in state…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/27337a6608b39ce6.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/DeleteJobCmd.java:68
protected JobEntity getJobToDelete(CommandContext commandContext) {
if (jobId == null) {
throw new ActivitiIllegalArgumentException("jobId is null");
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Deleting job {}", jobId);
}
JobEntity job = commandContext.getJobEntityManager().findJobById(jobId);
if (job == null) {
throw new ActivitiObjectNotFoundException("No job found with id '" + jobId + "'", Job.class);
}
// We need to check if the job was locked, ie acquired by the job acquisition thread
// This happens if the job was already acquired, but not yet executed.
// In that case, we can't allow to delete the job.
if (job.getLockOwner() != null) {
throw new ActivitiException("Cannot delete job when the job is being executed. Try again later.");
}
return job;
}
}
View on GitHub (pinned to d6d39ce1c6)