flowable/flowable-engine · error · FlowableException
No timer jobs found for plan item instance
Error message
No timer jobs found for plan item instance
What it means
RescheduleTimerJobCmd expects exactly one timer job for the given event listener plan item instance. When the timer job query returns no jobs it throws FlowableException 'No timer jobs found for plan item instance' because there is nothing to reschedule.
Solutions
- Query the job first: jobService/createTimerJobQuery().planItemInstanceId(id).count() and only reschedule when count == 1
- Check async executor state — a misconfigured async executor can leave no pending timer jobs
- Confirm tenant/category filters match the job's
- Catch FlowableException and treat already-fired timers as a benign case
Example fix
// before
rescheduleTimer(eventListenerInstanceId, newDate);
// after
if (jobService.createTimerJobQuery().planItemInstanceId(eventListenerInstanceId).count() == 1) {
rescheduleTimer(eventListenerInstanceId, newDate);
} else {
logger.warn("No (or multiple) timer jobs for {}, skipping reschedule", eventListenerInstanceId);
} Defensive patterns
Strategy: validation
Validate before calling
long n = jobService.createTimerJobQuery().planItemInstanceId(eventListenerInstanceId).count();
if (n == 0) throw new IllegalStateException("No timer job to reschedule for " + eventListenerInstanceId); Try / catch
try { reschedule(...); } catch (FlowableException e) { log.warn("Timer already fired or absent for {}", eventListenerInstanceId); } Prevention
- Check job existence before rescheduling
- Avoid double-reschedule calls
- Verify async executor configuration and tenant filters
When it happens
Trigger: Rescheduling an event listener instance that has no active timer job — e.g. the timer already fired, was cancelled, the listener never started a timer, or the job service query filters (tenant, category) exclude it.
Common situations: Calling reschedule twice (first call moves the job out of the timer job table); timer already expired and moved to the dead-letter/history tables; wrong tenant scoping hiding the job.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Multiple timer jobs found for plan item instance
- No plan item instance found for id
- Timer job not found for id
- A dynamically created plan item can only be injected into a…
- A dynamically created plan item can only be injected into a…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/3c4495ef5d4e89c9.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/RescheduleTimerJobCmd.java:64
this.newDueDate = newDueDate;
this.newDateValue = newDateValue;
}
@Override
public Job execute(CommandContext commandContext) {
String timerJobId = null;
PlanItemInstance planItemInstance = null;
JobService jobService = CommandContextUtil.getJobService(commandContext);
if (eventListenerInstanceId != null) {
planItemInstance = CommandContextUtil.getPlanItemInstanceEntityManager(commandContext).findById(eventListenerInstanceId);
if (planItemInstance == null) {
throw new FlowableObjectNotFoundException("No plan item instance found for id " + eventListenerInstanceId);
}
List<Job> timerJobs = jobService.createTimerJobQuery().planItemInstanceId(eventListenerInstanceId).list();
if (timerJobs == null || timerJobs.isEmpty()) {
throw new FlowableException("No timer jobs found for plan item instance " + eventListenerInstanceId);
}
if (timerJobs.size() > 1) {
throw new FlowableException("Multiple timer jobs found for plan item instance " + eventListenerInstanceId);
}
timerJobId = timerJobs.get(0).getId();
} else {
timerJobId = jobId;
}
TimerJobService timerJobService = CommandContextUtil.getTimerJobService(commandContext);
TimerJobEntity timerJob = timerJobService.findTimerJobById(timerJobId);
if (timerJob == null) {
throw new FlowableObjectNotFoundException("Timer job not found for id " + timerJobId);
}
View on GitHub (pinned to d6d39ce1c6)