flowable/flowable-engine · error · FlowableIllegalArgumentException
topic is required
Error message
topic is required
What it means
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.
Source
Thrown at modules/flowable-external-job-rest/src/main/java/org/flowable/external/job/rest/service/api/acquire/ExternalWorkerAcquireJobResource.java:77
@ApiResponse(code = 400, message = "Indicates the request was invalid."),
@ApiResponse(code = 403, message = "Indicates the user does not have the rights acquire the jobs."),
})
@PostMapping(value = "/acquire/jobs", produces = "application/json")
public List<AcquiredExternalWorkerJobResponse> acquireAndLockJobs(@RequestBody AcquireExternalWorkerJobRequest request) {
ExternalWorkerJobAcquireBuilder acquireBuilder = createExternalWorkerAcquireBuilder();
if (restApiInterceptor != null) {
restApiInterceptor.accessAcquireExternalWorkerJobs(acquireBuilder, request);
}
if (StringUtils.isNotEmpty(request.getTopic())) {
if (request.getLockDuration() != null) {
acquireBuilder.topic(request.getTopic(), request.getLockDuration());
} else {
throw new FlowableIllegalArgumentException("lockDuration is required");
}
} else {
throw new FlowableIllegalArgumentException("topic is required");
}
if (request.getScopeType() != null) {
acquireBuilder.scopeType(request.getScopeType());
}
if (StringUtils.isNotEmpty(request.getWorkerId())) {
List<AcquiredExternalWorkerJob> acquiredJobs = acquireBuilder
.acquireAndLock(request.getNumberOfTasks(), request.getWorkerId(), request.getNumberOfRetries());
return restResponseFactory.createAcquiredExternalWorkerJobResponseList(acquiredJobs);
} else {
throw new FlowableIllegalArgumentException("workerId is required");
}
}
@ApiOperation(value = "Complete an External Worker Jobs", code = 204, tags = { "Acquire and Execute" })
@ApiResponses({
@ApiResponse(code = 204, message = "Indicates the job was successfully completed."),View on GitHub (pinned to d6d39ce1c6)
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.
Example fix
// before
{"workerId": "w1", "lockDuration": 60000}
// after
{"topic": "invoice-processing", "workerId": "w1", "lockDuration": 60000} Defensive patterns
Strategy: validation
Validate before calling
if (request.topic() == null || request.topic().isBlank()) {
throw new IllegalArgumentException("topic is required");
} Try / catch
try {
acquire(request);
} catch (HttpClientErrorException.BadRequest e) {
log.error("Acquire rejected: {}", e.getResponseBodyAsString());
} Prevention
- 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.
When it happens
Trigger: POST /external-worker/acquire/jobs with missing topic field or topic:"" (StringUtils.isNotEmpty fails).
Common situations: 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.
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
- lockDuration is required
- workerId is required
- Can only complete BPMN or CMMN external job. Job with id '${
- Multipart request is required
- Multipart request with file content is required
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/40e3469d871a6251.
Report an issue: GitHub.