{"record":{"id":"74ad1549eb4643e4","repo":"flowable/flowable-engine","slug":"empty-timer-job-can-not-be-scheduled","errorCode":null,"errorMessage":"Empty timer job can not be scheduled","messagePattern":"Empty timer job can not be scheduled","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/asyncexecutor/DefaultJobManager.java","lineNumber":129,"sourceCode":"        String category = jobEntity.getCategory();\n        if (StringUtils.isEmpty(category)) {\n            // If the job has no category then we should not hint it, another node needs to run it\n            return false;\n        }\n\n        // Finally, the job should be hinted if the enabled job categories contain the job category\n        return enabledJobCategories.contains(category);\n    }\n\n    @Override\n    public void scheduleTimerJob(TimerJobEntity timerJob) {\n        jobServiceConfiguration.getTimerJobScheduler().scheduleTimerJob(timerJob);\n    }\n\n    @Override\n    public JobEntity moveTimerJobToExecutableJob(TimerJobEntity timerJob) {\n        if (timerJob == null) {\n            throw new FlowableException(\"Empty timer job can not be scheduled\");\n        }\n\n        JobEntity executableJob = createExecutableJobFromOtherJob(timerJob);\n        boolean insertSuccessful = jobServiceConfiguration.getJobEntityManager().insertJobEntity(executableJob);\n        if (insertSuccessful) {\n            jobServiceConfiguration.getTimerJobEntityManager().delete(timerJob);\n            triggerExecutorIfNeeded(executableJob);\n            return executableJob;\n        }\n        return null;\n    }\n\n    @Override\n    public void bulkMoveTimerJobsToExecutableJobs(List<TimerJobEntity> timerJobEntities) {\n\n        if (timerJobEntities == null || timerJobEntities.isEmpty()) {\n            throw new FlowableException(\"Empty timer jobs collection can not be scheduled\");\n        }","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/asyncexecutor/DefaultJobManager.java#L111-L147","documentation":"DefaultJobManager.moveTimerJobToExecutableJob promotes a TimerJobEntity to a runnable JobEntity when its due date arrives. A null timer job has nothing to schedule, so the method throws this FlowableException as a fail-fast precondition before creating the executable job.","triggerScenarios":"Passing null to JobManager.moveTimerJobToExecutableJob(timerJob), typically when a timer lookup/acquisition returned null and the result was forwarded without a null check.","commonSituations":"Custom async executor or timer acquisition logic that iterates results of a timer-job query and doesn't skip nulls; race conditions where the timer job was deleted between fetch and move.","solutions":["Check timerJob != null before calling moveTimerJobToExecutableJob and skip/log instead","Fix the upstream query/acquisition code that produced a null timer job","Wrap the call and treat FlowableException as an indicator of a lifecycle race, then re-fetch"],"exampleFix":"// before\njobManager.moveTimerJobToExecutableJob(timerJob); // may be null\n// after\nif (timerJob != null) {\n    jobManager.moveTimerJobToExecutableJob(timerJob);\n}","handlingStrategy":"validation","validationCode":"if (timerJob == null) { log.warn(\"No timer job to move to executable\"); return; }","typeGuard":"boolean canSchedule(TimerJobEntity t) { return t != null && t.getId() != null; }","tryCatchPattern":"try { jobManager.moveTimerJobToExecutableJob(timerJob); } catch (FlowableException e) { log.warn(\"Timer job became null/absent before move: {}\", e.getMessage()); }","preventionTips":["Null-check entities returned by timer-job queries before moving","Handle race conditions where jobs are deleted between fetch and move","Fail fast on null inputs at API boundaries"],"tags":["flowable","job-scheduling","null-check"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}