flowable/flowable-engine · error · FlowableObjectNotFoundException
Could not find a timer job with id '${jobId}'.
Error message
Could not find a timer job with id '${jobId}'. What it means
When moving a suspended timer job to the executable queue, the engine could not find the given job id. Flowable re-throws the engine's FlowableObjectNotFoundException with a standardized REST message so error messaging is consistent across the REST API.
Source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobResource.java:253
@ApiResponse(code = 204, message = "Indicates the timer job action was executed. Response-body is intentionally empty."),
@ApiResponse(code = 404, message = "Indicates the requested job was not found."),
@ApiResponse(code = 500, message = "Indicates the an exception occurred while executing the job. The status-description contains additional detail about the error. The full error-stacktrace can be fetched later on if needed.")
})
@PostMapping("/cmmn-management/timer-jobs/{jobId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void executeTimerJobAction(@ApiParam(name = "jobId") @PathVariable String jobId, @RequestBody TimerJobActionRequest actionRequest) {
if (actionRequest == null || !(MOVE_ACTION.equals(actionRequest.getAction()) || RESCHEDULE_ACTION.equals(actionRequest.getAction()))) {
throw new FlowableIllegalArgumentException("Invalid action, only 'move' or 'reschedule' are supported.");
}
Job job = getTimerJobById(jobId);
if (MOVE_ACTION.equals(actionRequest.getAction())) {
try {
managementService.moveTimerToExecutableJob(job.getId());
} catch (FlowableObjectNotFoundException e) {
// Re-throw to have consistent error-messaging across REST-api
throw new FlowableObjectNotFoundException("Could not find a timer job with id '" + jobId + "'.", Job.class);
}
} else if (RESCHEDULE_ACTION.equals(actionRequest.getAction())) {
if (actionRequest.getDueDate() == null) {
throw new FlowableIllegalArgumentException("Invalid reschedule timer action. Reschedule timer actions must have a valid due date");
}
try {
managementService.rescheduleTimeDateValueJob(job.getId(), actionRequest.getDueDate());
} catch (FlowableObjectNotFoundException e) {
// Re-throw to have consistent error-messaging across REST-api
throw new FlowableObjectNotFoundException("Could not find a timer job with id '" + jobId + "'.", Job.class);
}
}
}
@ApiOperation(value = "Execute a history job", tags = { "Jobs" }, code = 204)
@ApiResponses(value = {
@ApiResponse(code = 204, message = "Indicates the job was executed. Response-body is intentionally empty."),
@ApiResponse(code = 404, message = "Indicates the requested job was not found."),View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify the jobId exists by GETting the timer job or listing timer jobs first
- Confirm you are querying the same CMMN engine/database the job lives in
- Re-check that the job wasn't already moved or consumed
Example fix
// before
POST /cmmn-management/timer-jobs/unknown-id {"action":"move"}
// after
// look up a valid id first
GET /cmmn-management/timer-jobs?scopeId=myCase
then POST /cmmn-management/timer-jobs/{validId} {"action":"move"} Defensive patterns
Strategy: try-catch
Validate before calling
const job = await get(`/cmmn-management/timer-jobs/${jobId}`);
if (!job) throw new Error(`timer job ${jobId} not found`); Try / catch
try { await moveTimerJob(jobId); }
catch (e) { if (e.status === 404 && /Could not find a timer job/.test(e.message)) { /* refresh job list or skip */ } else throw e; } Prevention
- Re-fetch job ids before acting — jobs disappear when executed
- Keep CMMN and process-engine ids separate
- Log jobId plus engine/tenant to trace mismatched scopes
When it happens
Trigger: POST /cmmn-management/timer-jobs/{jobId} with action 'move' where jobId does not correspond to an existing timer job (already executed/moved, wrong engine, or never existed).
Common situations: Using a stale jobId after the timer already fired or was moved, mixing ids from the process-engine REST API with the CMMN API, or a typo in the id.
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
- Could not find a dead letter job with id '${jobId}'.
- Could not find a resource with id '<resourceName>' in deploy
- Could not find an app deployment with id '<deploymentId>
- Could not find a deployment with id '<deploymentId>'.
- Could not find an app deployment with id '<deploymentId>
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/2340630d23d6430e.
Report an issue: GitHub.