flowable/flowable-engine · error · ActivitiObjectNotFoundException
No job found with id '${jobId}'
Error message
No job found with id '${jobId}' What it means
DeleteJobCmd looks up the job by id via JobEntityManager.findJobById. When no JobEntity exists for the given id, the command aborts with ActivitiObjectNotFoundException carrying the missing job id and the expected entity class (Job.class). This prevents deletion of a non-existent job and gives callers a typed not-found signal.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/DeleteJobCmd.java:61
@Override
public Object execute(CommandContext commandContext) {
JobEntity jobToDelete = getJobToDelete(commandContext);
jobToDelete.delete();
return null;
}
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)
Solutions
- Verify the job id exists before deleting: ManagementService.createJobQuery(). jobId(id).singleResult() != null
- Check you are connected to the correct database/engine where the job was created
- Wrap deleteJob in a try-catch for ActivitiObjectNotFoundException and treat it as already-deleted/idempotent
- Re-check application logic that produced the id (e.g. using a processInstanceId instead of jobId)
Example fix
// before
managementService.deleteJob(jobId);
// after
Job job = managementService.createJobQuery().jobId(jobId).singleResult();
if (job != null) {
managementService.deleteJob(jobId);
} Defensive patterns
Strategy: try-catch
Validate before calling
Job job = managementService.createJobQuery().jobId(jobId).singleResult();
if (job == null) { /* skip: job already gone */ } Type guard
if (jobId != null && managementService.createJobQuery().jobId(jobId).singleResult() != null) { /* safe to delete */ } Try / catch
try {
managementService.deleteJob(jobId);
} catch (ActivitiObjectNotFoundException e) {
log.info("Job {} already deleted", jobId);
} Prevention
- Query the job before deleting
- Treat not-found on delete as idempotent success
- Confirm engine/database consistency across environments
When it happens
Trigger: Calling ManagementService.deleteJob(jobId), RuntimeService.deleteUserJob / deleteTimerJob, or any API that executes DeleteJobCmd, with a job id that does not exist (already deleted, wrong engine/database, or fabricated id).
Common situations: Deleting a job twice (e.g. after a failed async execution already removed it); pointing at a job id from another process definition instance or another Activiti/Flowable database; stale job ids cached in application code; job cleaned up by job executor timeout handling before manual delete.
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
- No job found with id
- Timer job with id '' doesn't have an exception stacktrace.
- Suspended job with id '' doesn't have an exception stacktrac
- Could not find a job with id ''.
- Could not find a timer job with id '${jobId}'.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/d99e6071b7738d81.
Report an issue: GitHub.