{"record":{"id":"05b347964fe68521","repo":"flowable/flowable-engine","slug":"workerid-is-required","errorCode":null,"errorMessage":"workerId is required","messagePattern":"workerId is required","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-external-job-rest/src/main/java/org/flowable/external/job/rest/service/api/acquire/ExternalWorkerAcquireJobResource.java","lineNumber":89,"sourceCode":"            if (request.getLockDuration() != null) {\n                acquireBuilder.topic(request.getTopic(), request.getLockDuration());\n            } else {\n                throw new FlowableIllegalArgumentException(\"lockDuration is required\");\n            }\n        } else {\n            throw new FlowableIllegalArgumentException(\"topic is required\");\n        }\n\n        if (request.getScopeType() != null) {\n            acquireBuilder.scopeType(request.getScopeType());\n        }\n\n        if (StringUtils.isNotEmpty(request.getWorkerId())) {\n            List<AcquiredExternalWorkerJob> acquiredJobs = acquireBuilder\n                    .acquireAndLock(request.getNumberOfTasks(), request.getWorkerId(), request.getNumberOfRetries());\n            return restResponseFactory.createAcquiredExternalWorkerJobResponseList(acquiredJobs);\n        } else {\n            throw new FlowableIllegalArgumentException(\"workerId is required\");\n        }\n    }\n\n    @ApiOperation(value = \"Complete an External Worker Jobs\", code = 204, tags = { \"Acquire and Execute\" })\n    @ApiResponses({\n            @ApiResponse(code = 204, message = \"Indicates the job was successfully completed.\"),\n            @ApiResponse(code = 400, message = \"Indicates the request was invalid.\"),\n            @ApiResponse(code = 403, message = \"Indicates the user does not have the rights complete the job.\"),\n            @ApiResponse(code = 404, message = \"Indicates the job does not exist.\"),\n    })\n    @PostMapping(value = \"/acquire/jobs/{jobId}/complete\", produces = \"application/json\")\n    public ResponseEntity<?> completeJob(@PathVariable String jobId, @RequestBody ExternalWorkerJobCompleteRequest request) {\n        String workerId = request.getWorkerId();\n        if (StringUtils.isEmpty(workerId)) {\n            throw new FlowableIllegalArgumentException(\"workerId is required\");\n        }\n\n        ExternalWorkerJob job = getExternalWorkerJobById(jobId);","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-external-job-rest/src/main/java/org/flowable/external/job/rest/service/api/acquire/ExternalWorkerAcquireJobResource.java#L71-L107","documentation":"FlowableIllegalArgumentException thrown in acquireAndLockJobs when workerId is empty or null. The engine records the workerId as the lock owner so other workers cannot complete the job; acquiring without it is rejected. Results in HTTP 400.","triggerScenarios":"POST /external-worker/acquire/jobs with missing or empty workerId field in the request body.","commonSituations":"Worker instance hostname/UUID not yet initialized when the first acquire fires; config key for worker id missing; field name mismatch during JSON binding.","solutions":["Set a unique workerId in the acquire request (e.g. hostname + UUID).","Initialize the worker identity before starting the acquire loop.","Fix JSON binding so workerId is not null."],"exampleFix":"// before\n{\"topic\": \"invoices\", \"lockDuration\": 60000}\n// after\n{\"topic\": \"invoices\", \"lockDuration\": 60000, \"workerId\": \"worker-1\"}","handlingStrategy":"validation","validationCode":"if (request.workerId() == null || request.workerId().isBlank()) {\n    throw new IllegalArgumentException(\"workerId is required\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    acquire(request);\n} catch (HttpClientErrorException.BadRequest e) {\n    log.error(\"Acquire rejected: {}\", e.getResponseBodyAsString());\n}","preventionTips":["Generate a stable unique workerId (hostname+UUID) at worker startup.","Initialize worker identity before entering the acquire loop.","Reuse the same workerId for acquire and all subsequent completions."],"tags":["rest","validation","external-worker","worker-id"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}