flowable/flowable-engine · error · FlowableIllegalArgumentException

worker id must not be empty

Error message

worker id must not be empty

What it means

UnacquireAllExternalWorkerJobsForWorkerCmd.execute throws this FlowableIllegalArgumentException when workerId is null or empty. The command needs a worker id to find and release all externally acquired jobs belonging to that worker, so an empty id makes the operation impossible. It is fail-fast validation before querying the external worker job entity manager.

Solutions

  1. Configure a stable, non-empty worker id before starting the external worker
  2. Guard the call site: only call unacquire when workerId is present
  3. Fix config/property loading that yields an empty worker id

Example fix

// before
externalWorkerJobService.unacquireAllExternalWorkerJobsForWorker(workerId, tenantId);
// after
if (workerId != null && !workerId.isBlank()) {
    externalWorkerJobService.unacquireAllExternalWorkerJobsForWorker(workerId, tenantId);
} else {
    logger.warn("Skip unacquire: worker id not set");
}
Defensive patterns

Strategy: validation

Validate before calling

if (workerId == null || workerId.isBlank()) {
    throw new IllegalStateException("worker id must be configured before unacquire");
}

Prevention

When it happens

Trigger: Calling JobService/unacquireAllExternalWorkerJobsForWorker(workerId, tenantId) with workerId null or ""; a worker client whose id was never configured (missing worker-id property) invoking cleanup on shutdown.

Common situations: External worker configuration where the worker id property is missing or blank; passing a variable initialized from a failed lookup; code refactoring dropped the assignment of the worker id.

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/df974cdd92fa0753. Report an issue: GitHub.

Appendix: source

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

import org.flowable.job.service.impl.persistence.entity.ExternalWorkerJobEntity;
import org.flowable.job.service.impl.persistence.entity.ExternalWorkerJobEntityManager;

public class UnacquireAllExternalWorkerJobsForWorkerCmd implements Command<Void> {

    protected final String workerId;
    protected final String tenantId;
    protected final JobServiceConfiguration jobServiceConfiguration;

    public UnacquireAllExternalWorkerJobsForWorkerCmd(String workerId, String tenantId, JobServiceConfiguration jobServiceConfiguration) {
        this.workerId = workerId;
        this.tenantId = tenantId;
        this.jobServiceConfiguration = jobServiceConfiguration;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        if (StringUtils.isEmpty(workerId)) {
            throw new FlowableIllegalArgumentException("worker id must not be empty");
        }

        ExternalWorkerJobEntityManager externalWorkerJobEntityManager = jobServiceConfiguration.getExternalWorkerJobEntityManager();

        List<ExternalWorkerJobEntity> jobEntities = externalWorkerJobEntityManager.findJobsByWorkerId(workerId);
        
        if (!jobEntities.isEmpty()) {
            if (StringUtils.isNotEmpty(tenantId)) {
                for (ExternalWorkerJobEntity externalWorkerJob : jobEntities) {
                    if (!tenantId.equals(externalWorkerJob.getTenantId())) {
                        throw new FlowableIllegalArgumentException("provided worker id has external worker jobs from different tenant.");
                    }
                }
            }
            
            for (ExternalWorkerJobEntity externalWorkerJob : jobEntities) {
                if (externalWorkerJob.isExclusive()) {
                    new UnlockExclusiveJobCmd(externalWorkerJob, jobServiceConfiguration).execute(commandContext);

View on GitHub (pinned to d6d39ce1c6)