{"record":{"id":"662d3784e1c624d2","repo":"flowable/flowable-engine","slug":"job-id-must-not-be-empty","errorCode":null,"errorMessage":"job id must not be empty","messagePattern":"job id 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/UnacquireExternalWorkerJobCmd.java","lineNumber":39,"sourceCode":"import org.flowable.job.service.impl.persistence.entity.ExternalWorkerJobEntity;\nimport org.flowable.job.service.impl.persistence.entity.ExternalWorkerJobEntityManager;\n\npublic class UnacquireExternalWorkerJobCmd implements Command<Void> {\n\n    protected final String jobId;\n    protected final String workerId;\n    protected final JobServiceConfiguration jobServiceConfiguration;\n\n    public UnacquireExternalWorkerJobCmd(String jobId, String workerId, JobServiceConfiguration jobServiceConfiguration) {\n        this.jobId = jobId;\n        this.workerId = workerId;\n        this.jobServiceConfiguration = jobServiceConfiguration;\n    }\n\n    @Override\n    public Void execute(CommandContext commandContext) {\n        if (StringUtils.isEmpty(jobId)) {\n            throw new FlowableIllegalArgumentException(\"job id must not be empty\");\n        }\n\n        if (StringUtils.isEmpty(workerId)) {\n            throw new FlowableIllegalArgumentException(\"worker id must not be empty\");\n        }\n\n        ExternalWorkerJobEntityManager externalWorkerJobEntityManager = jobServiceConfiguration.getExternalWorkerJobEntityManager();\n\n        ExternalWorkerJobEntity jobEntity = externalWorkerJobEntityManager.findById(jobId);\n        if (jobEntity == null) {\n            throw new FlowableException(\"Could not find job for id \" + jobId);\n        }\n        \n        if (!jobEntity.getLockOwner().equals(workerId)) {\n            throw new FlowableException(jobEntity + \" is locked with a different worker id\");\n        }\n\n        jobEntity.setLockExpirationTime(null);","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/UnacquireExternalWorkerJobCmd.java#L21-L57","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nexternalWorkerJobAcquireService.unacquireExternalWorkerJob(null, workerId);\n// after\nif (job != null && job.getId() != null) {\n    externalWorkerJobAcquireService.unacquireExternalWorkerJob(job.getId(), workerId);\n}","handlingStrategy":"validation","validationCode":"if (job == null || job.getId() == null || job.getId().isEmpty()) {\n    throw new IllegalStateException(\"Cannot unacquire: job id missing\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["validation","flowable","external-worker"],"backgroundTag":"empty-required-field","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}