flowable/flowable-engine · error · FlowableIllegalArgumentException

jobId is null

Error message

jobId is null

What it means

ExecuteAsyncRunnableJobCmd validates both dependencies: if its injected jobEntityManager is null it throws "jobEntityManager is null", and if jobId is null it throws FlowableIllegalArgumentException("jobId is null"). Unlike ExecuteAsyncJobCmd it does not fall back to the configuration, so both fields must be supplied explicitly.

Source

Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/ExecuteAsyncRunnableJobCmd.java:64

    public ExecuteAsyncRunnableJobCmd(String jobId, JobInfoEntityManager<? extends JobInfoEntity> jobEntityManager,
            JobServiceConfiguration jobServiceConfiguration, boolean unlock) {
        
        this.jobId = jobId;
        this.jobEntityManager = jobEntityManager;
        this.jobServiceConfiguration = jobServiceConfiguration;
        this.unlock = unlock;
    }

    @Override
    public Object execute(CommandContext commandContext) {
        
        if (jobEntityManager == null) {
            throw new FlowableIllegalArgumentException("jobEntityManager is null");
        }

        if (jobId == null) {
            throw new FlowableIllegalArgumentException("jobId is null");
        }

        // We need to refetch the job, as it could have been deleted by another concurrent job
        // For example: an embedded subprocess with a couple of async tasks and a timer on the boundary of the subprocess
        // when the timer fires, all executions and thus also the jobs inside of the embedded subprocess are destroyed.
        // However, the async task jobs could already have been fetched and put in the queue.... while in reality they have been deleted.
        // A refetch is thus needed here to be sure that it exists for this transaction.

        JobInfoEntity job = jobEntityManager.findById(jobId);
        if (job == null) {
            LOGGER.debug("Job does not exist anymore and will not be executed. It has most likely been deleted "
                    + "as part of another concurrent part of the process instance.");
            return null;
        }

        if (LOGGER.isDebugEnabled()) {
            if (job instanceof JobEntity) {
                LOGGER.debug("Executing async job {}", job.getId());

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a non-null JobEntityManager obtained from JobServiceConfiguration when constructing the command.
  2. Ensure the job id is set on the entity before dispatching the runnable.
  3. Prefer ExecuteAsyncJobCmd, which resolves the entity manager from the configuration as a fallback.
  4. Add null checks in the code that instantiates this command so failures surface at your boundary.

Example fix

// before
new ExecuteAsyncRunnableJobCmd(null, jobId); // jobEntityManager is null
// after
new ExecuteAsyncRunnableJobCmd(jobServiceConfiguration.getJobEntityManager(), jobId);
Defensive patterns

Strategy: validation

Validate before calling

if (jobEntityManager == null) { throw new IllegalArgumentException("jobEntityManager required"); }
if (jobId == null) { throw new IllegalArgumentException("jobId required"); }

Try / catch

try { commandExecutor.execute(cmd); } catch (FlowableIllegalArgumentException e) { LOGGER.error("Bad ExecuteAsyncRunnableJobCmd input: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Executing new ExecuteAsyncRunnableJobCmd(null, ...) or new ExecuteAsyncRunnableJobCmd(em, null) via the command executor; async runnable dispatch paths that lost the entity manager reference.

Common situations: Hand-wiring the command in tests or custom code without providing the entity manager; job runnable factories passing a job whose id was never assigned; misconfiguration where a custom JobEntityManager bean is missing.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/646767d28628a2d6. Report an issue: GitHub.