{"record":{"id":"a76319447919cfff","repo":"flowable/flowable-engine","slug":"workerid-must-not-be-empty-a76319","errorCode":null,"errorMessage":"workerId must not be empty","messagePattern":"workerId must not be empty","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/AbstractExternalWorkerJobCmd.java","lineNumber":62,"sourceCode":"        runJobLogic(externalWorkerJob, commandContext);\n        if (externalWorkerJob.isExclusive()) {\n            // Part of the same transaction to avoid a race condition with the\n            // potentially new jobs (wrt process instance locking) that are created\n            // during the execution of the original job\n            new UnlockExclusiveJobCmd(externalWorkerJob, jobServiceConfiguration).execute(commandContext);\n        }\n        return null;\n    }\n\n    protected abstract void runJobLogic(ExternalWorkerJobEntity externalWorkerJob, CommandContext commandContext);\n\n    protected ExternalWorkerJobEntity resolveJob() {\n        if (StringUtils.isEmpty(externalJobId)) {\n            throw new FlowableIllegalArgumentException(\"externalJobId must not be empty\");\n        }\n\n        if (StringUtils.isEmpty(workerId)) {\n            throw new FlowableIllegalArgumentException(\"workerId must not be empty\");\n        }\n\n        ExternalWorkerJobEntityManager externalWorkerJobEntityManager = jobServiceConfiguration.getExternalWorkerJobEntityManager();\n\n        ExternalWorkerJobEntity job = externalWorkerJobEntityManager.findById(externalJobId);\n\n        if (job == null) {\n            throw new FlowableObjectNotFoundException(\"No External Worker job found for id: \" + externalJobId, ExternalWorkerJobEntity.class);\n        }\n\n        if (!Objects.equals(workerId, job.getLockOwner())) {\n            throw new FlowableIllegalArgumentException(workerId + \" does not hold a lock on the requested job\");\n        }\n\n        return job;\n    }\n}\n","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/AbstractExternalWorkerJobCmd.java#L44-L80","documentation":"Thrown by resolveJob() in AbstractExternalWorkerJobCmd when workerId is null or empty. Flowable requires the worker identity because the command later verifies that this worker actually holds the lock on the job (lock-owner check). An empty workerId means the worker did not identify itself when completing/terminating/failing a job.","triggerScenarios":"Completing, failing or terminating an external worker job without calling workerId(...) on the builder; the worker framework passing a null/empty worker identifier; constructing the command object directly with workerId unset.","commonSituations":"Worker instances configured without a unique workerId; refactored code where the builder field was removed; a generic job-handling wrapper that forwards only the job id.","solutions":["Call workerId(...) on the ExternalWorkerJobCompletionBuilder with the same id used when acquiring the job","Give every worker instance a stable, non-empty workerId in configuration","Log the workerId at acquisition time and assert it is non-empty before executing job lifecycle commands"],"exampleFix":"// before\nmanagementService.createExternalWorkerJobCompletionBuilder(externalJobId).complete();\n// after\nmanagementService.createExternalWorkerJobCompletionBuilder(externalJobId)\n    .workerId(workerId)\n    .complete();","handlingStrategy":"validation","validationCode":"if (workerId == null || workerId.isEmpty()) {\n    throw new IllegalArgumentException(\"workerId must be configured before job lifecycle calls\");\n}","typeGuard":"boolean hasWorkerId(String id) { return id != null && !id.trim().isEmpty(); }","tryCatchPattern":"try {\n    completionBuilder.externalJobId(jobId).workerId(workerId).complete();\n} catch (FlowableIllegalArgumentException e) {\n    LOGGER.error(\"Completion rejected: {}\", e.getMessage());\n}","preventionTips":["Configure a stable workerId per worker at startup and fail fast if blank","Reuse the same constant/provider for workerId across acquire and completion","Unit-test the completion path with an unset workerId to catch regressions"],"tags":["validation","flowable","external-worker-job"],"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-14T05:17:10.506Z"}