flowable/flowable-engine · error · FlowableObjectNotFoundException
Could not find a job with id
Error message
Could not find a job with id '${jobId}'. What it means
The REST endpoint DELETE /management/jobs/{jobId} catches FlowableObjectNotFoundException from managementService.deleteJob and re-throws it with a consistent message: no job with the given id exists in the runtime job table (ACT_RU_JOB). Flowable throws this because a delete can only target an existing job entity.
Solutions
- Confirm the job id by querying GET /management/jobs/{jobId} before deleting
- If the job is a timer, suspended, deadletter, or history job, use the matching endpoint (/management/timer-jobs/..., /management/suspended-jobs/..., etc.)
- Catch FlowableObjectNotFoundException / handle 404 and treat deletion as idempotent no-op
Example fix
// before
restTemplate.delete("/management/jobs/" + someTimerJobId); // 404
// after
restTemplate.delete("/management/timer-jobs/" + someTimerJobId); Defensive patterns
Strategy: validation
Validate before calling
Job job = managementService.createJobQuery().jobId(jobId).singleResult();
if (job == null) { /* skip or use correct endpoint */ } Try / catch
try {
managementService.deleteJob(jobId);
} catch (FlowableObjectNotFoundException e) {
// already deleted or wrong table
} Prevention
- Resolve job type first (job vs timer vs suspended vs deadletter) and use the matching endpoint
- Treat deletes as idempotent; tolerate 404
- Refresh job ids from a live query, not cached snapshots
When it happens
Trigger: DELETE /management/jobs/{jobId} with a jobId that does not exist, was already deleted, or exists only in another table (timer/suspended/deadletter/history jobs are separate tables — a timer job id passed here also fails).
Common situations: Using an id from the wrong job table (e.g. timer job id against the plain jobs endpoint); retrying a delete after the job already executed and was removed; stale ids after engine restart or cleanup.
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
- Could not find a batch with id
- Could not find a job with id ''.
- A request body was expected when bulk updating tasks.
- A request body was expected when executing the form submit.
- Attachment name is required.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/1942c6d9e2702ca6.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/management/JobResource.java:140
@ApiOperation(value = "Delete a job", tags = { "Jobs" }, code = 204)
@ApiResponses(value = {
@ApiResponse(code = 204, message = "Indicates the job was found and has been deleted. Response-body is intentionally empty."),
@ApiResponse(code = 404, message = "Indicates the requested job was not found.")
})
@DeleteMapping("/management/jobs/{jobId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteJob(@ApiParam(name = "jobId") @PathVariable String jobId) {
Job job = getJobById(jobId);
if (restApiInterceptor != null) {
restApiInterceptor.deleteJob(job);
}
try {
managementService.deleteJob(jobId);
} catch (FlowableObjectNotFoundException aonfe) {
// Re-throw to have consistent error-messaging across REST-api
throw new FlowableObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
}
}
@ApiOperation(value = "Delete a timer job", tags = { "Jobs" }, code = 204)
@ApiResponses(value = {
@ApiResponse(code = 204, message = "Indicates the job was found and has been deleted. Response-body is intentionally empty."),
@ApiResponse(code = 404, message = "Indicates the requested job was not found.")
})
@DeleteMapping("/management/timer-jobs/{jobId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteTimerJob(@ApiParam(name = "jobId") @PathVariable String jobId) {
Job job = getTimerJobById(jobId);
if (restApiInterceptor != null) {
restApiInterceptor.deleteJob(job);
}
try {
managementService.deleteTimerJob(jobId);View on GitHub (pinned to d6d39ce1c6)