flowable/flowable-engine · error · FlowableIllegalArgumentException
job id must not be empty
Error message
job id must not be empty
What it means
UnacquireExternalWorkerJobCmd.execute throws this FlowableIllegalArgumentException when jobId is null or empty. The command releases a single externally acquired job identified by its id; without a valid job id the release cannot proceed. This is the first check in execute, before the worker id check.
Solutions
- Always propagate the JobEntity.getId() from the acquired job into the handler and use it in unacquire
- Null/empty-check jobId at the handler boundary before calling unacquire
- Ensure the acquired job object is retained (not GC'd/reassigned) through the handler lifecycle
Example fix
// before
externalWorkerJobAcquireService.unacquireExternalWorkerJob(null, workerId);
// after
if (job != null && job.getId() != null) {
externalWorkerJobAcquireService.unacquireExternalWorkerJob(job.getId(), workerId);
} Defensive patterns
Strategy: validation
Validate before calling
if (job == null || job.getId() == null || job.getId().isEmpty()) {
throw new IllegalStateException("Cannot unacquire: job id missing");
} Prevention
- Always carry JobEntity.getId() into handlers and use it for release
- Null-check job payloads before result handling
- Do not default job ids to null/empty in handler wiring
When it happens
Trigger: Calling unacquireExternalWorkerJob(jobId, workerId) with an empty jobId, e.g. the id variable was lost during job handling, or a result handler ran after the job entity was no longer in scope and its id defaulted to null.
Common situations: External worker task handlers storing/parsing the job id incorrectly; passing null after a failed JSON payload extraction; framework code invoking unacquire on shutdown with an unset job 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
- at least one of userId or groups must be provided
- Cannot combine onlyBpmn() with onlyCmmn() in the same query
- Cannot combine onlyCmmn() with onlyBpmn() in the same query
- Cannot combine scopeType(String) with onlyBpmn() in the…
- Cannot combine scopeType(String) with onlyCmmn() in the…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/662d3784e1c624d2.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/UnacquireExternalWorkerJobCmd.java:39
import org.flowable.job.service.impl.persistence.entity.ExternalWorkerJobEntity;
import org.flowable.job.service.impl.persistence.entity.ExternalWorkerJobEntityManager;
public class UnacquireExternalWorkerJobCmd implements Command<Void> {
protected final String jobId;
protected final String workerId;
protected final JobServiceConfiguration jobServiceConfiguration;
public UnacquireExternalWorkerJobCmd(String jobId, String workerId, JobServiceConfiguration jobServiceConfiguration) {
this.jobId = jobId;
this.workerId = workerId;
this.jobServiceConfiguration = jobServiceConfiguration;
}
@Override
public Void execute(CommandContext commandContext) {
if (StringUtils.isEmpty(jobId)) {
throw new FlowableIllegalArgumentException("job id must not be empty");
}
if (StringUtils.isEmpty(workerId)) {
throw new FlowableIllegalArgumentException("worker id must not be empty");
}
ExternalWorkerJobEntityManager externalWorkerJobEntityManager = jobServiceConfiguration.getExternalWorkerJobEntityManager();
ExternalWorkerJobEntity jobEntity = externalWorkerJobEntityManager.findById(jobId);
if (jobEntity == null) {
throw new FlowableException("Could not find job for id " + jobId);
}
if (!jobEntity.getLockOwner().equals(workerId)) {
throw new FlowableException(jobEntity + " is locked with a different worker id");
}
jobEntity.setLockExpirationTime(null);View on GitHub (pinned to d6d39ce1c6)