{"record":{"id":"c41d27099acd90be","repo":"flowable/flowable-engine","slug":"only-jobs-with-type-jobentity-are-supported-to-be","errorCode":null,"errorMessage":"Only jobs with type JobEntity are supported to be executed. It was ","messagePattern":"Only jobs with type JobEntity are supported to be executed\\. It was ","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":337,"sourceCode":"\n        return historyJobEntity;\n    }\n\n    @Override\n    public void execute(JobInfo job) {\n        if (job instanceof HistoryJobEntity) {\n            callHistoryJobProcessors(HistoryJobProcessorContext.Phase.BEFORE_EXECUTE, (HistoryJobEntity) job);\n            executeHistoryJob((HistoryJobEntity) job);\n        } else if (job instanceof JobEntity) {\n            callJobProcessors(JobProcessorContext.Phase.BEFORE_EXECUTE, (JobEntity) job);\n            if (Job.JOB_TYPE_MESSAGE.equals(((Job) job).getJobType())) {\n                executeMessageJob((JobEntity) job);\n            } else if (Job.JOB_TYPE_TIMER.equals(((Job) job).getJobType())) {\n                executeTimerJob((JobEntity) job);\n            }\n\n        } else {\n            throw new FlowableException(\"Only jobs with type JobEntity are supported to be executed. It was \" + job);\n        }\n    }\n\n    @Override\n    public void unacquire(JobInfo job) {\n\n        if (job instanceof HistoryJob) {\n\n            HistoryJobEntity jobEntity = jobServiceConfiguration.getHistoryJobEntityManager().findById(job.getId());\n            if (jobEntity == null) {\n                LOGGER.debug(\"History Job {} does not exist anymore and will not be unacquired. It has most likely been deleted \"\n                        + \"e.g. as part of another concurrent part of a process / case instance.\", job.getId());\n                return;\n            }\n\n            jobEntity.setLockExpirationTime(null);\n            jobEntity.setLockOwner(null);\n","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/asyncexecutor/DefaultJobManager.java#L319-L355","documentation":"DefaultJobManager.execute(Job) only knows how to execute JobEntity instances. If the async executor hands it a JobInfo (or any other non-JobEntity job implementation) it cannot be cast to a message or timer JobEntity, so Flowable throws this FlowableException. It is an internal contract violation between the async executor's job acquisition and the job manager.","triggerScenarios":"Calling DefaultJobManager.execute(Job) with a Job implementation that is not a JobEntity (e.g. a custom JobInfo implementation passed directly, or a custom async executor feeding non-entity jobs).","commonSituations":"Custom async executor implementations or test harnesses that wrap jobs in a JobInfo facade and pass the wrapper instead of the underlying JobEntity; upgrading Flowable versions where job interfaces changed.","solutions":["Ensure the object passed to jobManager.execute(job) is a JobEntity instance (e.g. the loaded MessageJobEntity/TimerJobEntity), not a JobInfo wrapper.","If using a custom async executor, fetch the actual JobEntity from the job entity manager before calling execute().","Check Flowable version compatibility between the engine and any custom async-executor integration code."],"exampleFix":"// before\njobInfo = acquireJob();\njobManager.execute(jobInfo); // JobInfo, not JobEntity\n\n// after\nJobEntity jobEntity = jobEntityManager.findById(jobInfo.getId());\njobManager.execute(jobEntity);","handlingStrategy":"type-guard","validationCode":"if (!(job instanceof JobEntity)) { throw new IllegalArgumentException(\"execute() requires a JobEntity, got: \" + job.getClass()); }\njobManager.execute((JobEntity) job);","typeGuard":"boolean isExecutableJob(Job job) { return job instanceof JobEntity; }","tryCatchPattern":"try { jobManager.execute(job); } catch (FlowableException e) { if (e.getMessage().startsWith(\"Only jobs with type JobEntity\")) { JobEntity entity = jobEntityManager.findById(job.getId()); jobManager.execute(entity); } else throw e; }","preventionTips":["Never pass JobInfo wrappers directly into DefaultJobManager.execute.","Resolve the underlying JobEntity via the job entity manager first.","Unit-test custom async executors with real JobEntity instances."],"tags":["flowable","job-executor","type-mismatch","internal-api"],"backgroundTag":"type-mismatch","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"}