{"record":{"id":"40e3469d871a6251","repo":"flowable/flowable-engine","slug":"topic-is-required","errorCode":null,"errorMessage":"topic is required","messagePattern":"topic 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":77,"sourceCode":"            @ApiResponse(code = 400, message = \"Indicates the request was invalid.\"),\n            @ApiResponse(code = 403, message = \"Indicates the user does not have the rights acquire the jobs.\"),\n    })\n    @PostMapping(value = \"/acquire/jobs\", produces = \"application/json\")\n    public List<AcquiredExternalWorkerJobResponse> acquireAndLockJobs(@RequestBody AcquireExternalWorkerJobRequest request) {\n        ExternalWorkerJobAcquireBuilder acquireBuilder = createExternalWorkerAcquireBuilder();\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.accessAcquireExternalWorkerJobs(acquireBuilder, request);\n        }\n\n        if (StringUtils.isNotEmpty(request.getTopic())) {\n            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.\"),","sourceCodeStart":59,"sourceCodeEnd":95,"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#L59-L95","documentation":"FlowableIllegalArgumentException thrown in acquireAndLockJobs when the request's topic is empty or null. Acquiring external worker jobs is topic-based, so a topic must be supplied. Results in HTTP 400.","triggerScenarios":"POST /external-worker/acquire/jobs with missing topic field or topic:\"\" (StringUtils.isNotEmpty fails).","commonSituations":"Client sends an empty body or partially built request object; topic name derived from config that is unset; field naming mismatch leaving topic null after deserialization.","solutions":["Include a non-empty topic in the acquire request body.","Ensure the configured topic name is present in the client's configuration.","Validate the request client-side before sending."],"exampleFix":"// before\n{\"workerId\": \"w1\", \"lockDuration\": 60000}\n// after\n{\"topic\": \"invoice-processing\", \"workerId\": \"w1\", \"lockDuration\": 60000}","handlingStrategy":"validation","validationCode":"if (request.topic() == null || request.topic().isBlank()) {\n    throw new IllegalArgumentException(\"topic is required\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    acquire(request);\n} catch (HttpClientErrorException.BadRequest e) {\n    log.error(\"Acquire rejected: {}\", e.getResponseBodyAsString());\n}","preventionTips":["Validate topic is a non-empty string before sending.","Ensure the topic is loaded from configuration before first acquire.","Use constants/shared definitions for topic names between engine and worker."],"tags":["rest","validation","external-worker","topic"],"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"}