flowable/flowable-engine · error · FlowableIllegalArgumentException

workerId must not be empty

Error message

workerId must not be empty

What it means

FlowableIllegalArgumentException thrown by resolveJob when the workerId passed to the external worker command is null or empty. The workerId identifies which worker is acting on the job and is required for identity-link bookkeeping and validation.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/AbstractExternalWorkerJobCmd.java:78

    }

    protected abstract void runJobLogic(ExternalWorkerJobEntity externalWorkerJob, CommandContext commandContext);

    protected void moveExternalWorkerJobToExecutableJob(ExternalWorkerJobEntity externalWorkerJob, CommandContext commandContext) {
        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
        cmmnEngineConfiguration.getJobServiceConfiguration().getJobManager().moveExternalWorkerJobToExecutableJob(externalWorkerJob);

        cmmnEngineConfiguration.getIdentityLinkServiceConfiguration().getIdentityLinkService()
                .deleteIdentityLinksByScopeIdAndType(externalWorkerJob.getCorrelationId(), ScopeTypes.EXTERNAL_WORKER);
    }

    protected ExternalWorkerJobEntity resolveJob(CommandContext commandContext) {
        if (StringUtils.isEmpty(externalJobId)) {
            throw new FlowableIllegalArgumentException("externalJobId must not be empty");
        }

        if (StringUtils.isEmpty(workerId)) {
            throw new FlowableIllegalArgumentException("workerId must not be empty");
        }

        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
        ExternalWorkerJobEntityManager externalWorkerJobEntityManager = cmmnEngineConfiguration.getJobServiceConfiguration().getExternalWorkerJobEntityManager();

        ExternalWorkerJobEntity job = externalWorkerJobEntityManager.findById(externalJobId);

        if (job == null) {
            throw new FlowableObjectNotFoundException("No External Worker job found for id: " + externalJobId, ExternalWorkerJobEntity.class);
        }

        if (!Objects.equals(workerId, job.getLockOwner())) {
            throw new FlowableIllegalArgumentException(workerId + " does not hold a lock on the requested job");
        }

        return job;
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass the same workerId used during job acquisition into the completion/failure builder.
  2. Check application configuration so the worker id is populated (non-empty) at startup.
  3. Swap arguments if job id and worker id were transposed in the builder call.

Example fix

// before
cmmnExternalWorkerServiceProvider.completeBuilder("", externalJobId).complete();
// after
cmmnExternalWorkerServiceProvider.completeBuilder("order-worker-1", externalJobId).complete();
Defensive patterns

Strategy: validation

Validate before calling

if (workerId == null || workerId.isBlank())
    throw new IllegalArgumentException("workerId must be configured before handling external worker jobs");

Try / catch

try { completeBuilder(workerId, externalJobId).complete(); }
catch (FlowableIllegalArgumentException e) { if (e.getMessage().equals("workerId must not be empty")) { reloadWorkerConfig(); } }

Prevention

When it happens

Trigger: Calling completeBuilder/failureBuilder with an empty workerId, e.g., workerId field never set from configuration or the acquire response.

Common situations: Worker application missing its configured worker id (empty env var/config key); passing job id where workerId is expected due to argument order confusion.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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