flowable/flowable-engine · error · FlowableIllegalArgumentException

worker id is required

Error message

worker id is required

What it means

FlowableIllegalArgumentException thrown by unacquireJobs when the request body has an empty or null workerId. The worker id identifies which worker's locks to release, so it is mandatory. The check runs before any engine interaction.

Solutions

  1. Include the workerId field in the unacquire request body.
  2. Validate workerId is non-blank on the client before calling the endpoint.
  3. Check the code constructing UnacquireExternalWorkerJobsRequest to ensure it copies the worker id.

Example fix

// before
POST /external-worker-job/unacquire/jobs {"tenantId":"t1"}
// after
POST /external-worker-job/unacquire/jobs {"workerId":"worker-1","tenantId":"t1"}
Defensive patterns

Strategy: validation

Validate before calling

if (workerId == null || workerId.isBlank()) { throw new IllegalArgumentException("workerId is required"); }

Type guard

boolean validWorkerId(String id) { return id != null && !id.isBlank(); }

Try / catch

try { unacquireJobs(request); } catch (FlowableIllegalArgumentException e) { if (e.getMessage().equals("worker id is required")) { supplyWorkerIdAndRetry(); } else { throw e; } }

Prevention

When it happens

Trigger: POST /external-worker-job/unacquire/jobs with a body missing 'workerId' or with workerId="" (UnacquireExternalWorkerJobsRequest without workerId).

Common situations: Clients that only send tenantId; DTOs deserialized from JSON lacking the field; test scripts posting empty bodies.

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

Appendix: source

Thrown at modules/flowable-external-job-rest/src/main/java/org/flowable/external/job/rest/service/api/acquire/ExternalWorkerUnacquireJobResource.java:57

    public ExternalWorkerUnacquireJobResource(ExternalJobRestResponseFactory restResponseFactory) {
        this.restResponseFactory = restResponseFactory;
    }

    @ApiOperation(value = "Unacquire External Worker Jobs", tags = { "Unacquire" })
    @ApiResponses({
            @ApiResponse(code = 204, message = "Indicates the jobs were unacquired."),
            @ApiResponse(code = 400, message = "Indicates the request was invalid."),
            @ApiResponse(code = 403, message = "Indicates the user does not have the rights to unacquire the jobs."),
    })
    @PostMapping(value = "/unacquire/jobs", produces = "application/json")
    public ResponseEntity<?> unacquireJobs(@RequestBody UnacquireExternalWorkerJobsRequest request) {
        if (restApiInterceptor != null) {
            restApiInterceptor.accessUnacquireExternalWorkerJobs(request);
        }

        if (StringUtils.isEmpty(request.getWorkerId())) {
            throw new FlowableIllegalArgumentException("worker id is required");
        }

        unaquireExternalWorkerJobs(request.getWorkerId(), request.getTenantId());
        
        return ResponseEntity.noContent().build();
    }

    @ApiOperation(value = "Unaquire an External Worker Job", code = 204, tags = { "Unacquire" })
    @ApiResponses({
            @ApiResponse(code = 204, message = "Indicates the job was successfully unaquired."),
            @ApiResponse(code = 400, message = "Indicates the request was invalid."),
            @ApiResponse(code = 403, message = "Indicates the user does not have the rights to unacquire the job."),
            @ApiResponse(code = 404, message = "Indicates the job does not exist."),
    })
    @PostMapping(value = "/unacquire/jobs/{jobId}", produces = "application/json")
    public ResponseEntity<?> unaquireJob(@PathVariable String jobId, @RequestBody UnacquireExternalWorkerJobsRequest request) {
        String workerId = request.getWorkerId();
        if (StringUtils.isEmpty(workerId)) {

View on GitHub (pinned to d6d39ce1c6)