flowable/flowable-engine · error · FlowableIllegalArgumentException

workerId must not be empty

Error message

workerId must not be empty

What it means

Thrown by AcquireExternalWorkerJobsCmd.execute() when workerId is null or empty. The workerId identifies the locker: it is stored as lock owner on the jobs it acquires and later checked on completion, so Flowable requires a non-empty value at acquisition time.

Solutions

  1. Set a non-empty workerId before starting the acquisition loop and pass it to acquireAndLock
  2. Validate worker configuration at startup: throw/fail deploy if workerId is blank
  3. Generate a stable unique id (hostname + UUID) if instances don't have a natural identity

Example fix

// before
builder.topic(topic).acquireAndLock(5, workerIdFromConfig, 60000); // empty config
// after
if (workerId == null || workerId.isEmpty()) {
    throw new IllegalStateException("workerId must be configured");
}
builder.topic(topic).acquireAndLock(5, workerId, 60000);
Defensive patterns

Strategy: validation

Validate before calling

if (workerId == null || workerId.isEmpty()) {
    throw new IllegalArgumentException("workerId must be set before acquiring jobs");
}

Type guard

boolean hasWorkerId(String id) { return id != null && !id.trim().isEmpty(); }

Try / catch

try {
    acquireBuilder.topic(topic).acquireAndLock(numberOfJobs, workerId, lockDuration);
} catch (FlowableIllegalArgumentException e) {
    LOGGER.error("Acquire rejected: {}", e.getMessage());
}

Prevention

When it happens

Trigger: acquireAndLock(numberOfJobs, null, lockDuration); worker identity not initialized before the poll loop starts; configuration property for worker id missing so an empty string is passed.

Common situations: A worker started without its instance-name/worker-id property; race where the scheduler thread fires before configuration is bound; refactored code dropping the workerId parameter.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

        this.workerId = workerId;
        this.numberOfJobs = numberOfJobs;
        this.builder = builder;
        this.jobServiceConfiguration = jobServiceConfiguration;
    }

    @Override
    public List<AcquiredExternalWorkerJob> execute(CommandContext commandContext) {
        String topic = builder.getTopic();
        if (StringUtils.isEmpty(topic)) {
            throw new FlowableIllegalArgumentException("topic must not be empty");
        }

        if (numberOfJobs < 1) {
            throw new FlowableIllegalArgumentException("requested number of jobs must not be smaller than 1");
        }

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

        ExternalWorkerJobEntityManager externalWorkerJobEntityManager = jobServiceConfiguration.getExternalWorkerJobEntityManager();
        InternalJobManager internalJobManager = jobServiceConfiguration.getInternalJobManager();

        List<ExternalWorkerJobEntity> jobs = externalWorkerJobEntityManager.findExternalJobsToExecute(builder, numberOfJobs);

        int lockTimeInMillis = (int) builder.getLockDuration().abs().toMillis();
        List<AcquiredExternalWorkerJob> acquiredJobs = new ArrayList<>(jobs.size());

        for (ExternalWorkerJobEntity job : jobs) {
            lockJob(commandContext, job, lockTimeInMillis);
            Map<String, Object> variables = null;
            if (internalJobManager != null) {
                variables = internalJobManager.resolveVariablesForExternalWorkerJob(job);

                if (job.isExclusive()) {
                    internalJobManager.lockJobScope(job);

View on GitHub (pinned to d6d39ce1c6)