flowable/flowable-engine · error · FlowableException
is not bpmn scoped. This command can only handle bpmn…
Error message
{externalWorkerJob} is not bpmn scoped. This command can only handle bpmn scoped external worker jobs What it means
AbstractExternalWorkerJobCmd.execute resolves the external worker job and requires it to be BPMN-scoped, detected via a non-null processInstanceId. Jobs belonging to other scopes (e.g. CMMN case instances) have no process instance id, so this FlowableException is thrown and the command's job logic is skipped.
Solutions
- Use the case-worker command/API (cmmn engine's external worker job handling) for jobs whose processInstanceId is null.
- Filter acquired jobs by scope before dispatching: only call BPMN-specific complete/fail commands when job.getScopeType()/processInstanceId indicates BPMN.
- Fix the acquisition query to restrict to BPMN-scoped jobs only (correct scope filters in the acquire command).
Example fix
// before
jobService.complete(externalWorkerJob.getId(), workerId, variables); // job may be CMMN-scoped
// after
if (externalWorkerJob.getProcessInstanceId() != null) {
jobService.complete(externalWorkerJob.getId(), workerId, variables);
} else {
caseService.complete(externalWorkerJob.getId(), workerId, variables);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (externalWorkerJob.getProcessInstanceId() == null) {
// route to CMMN handling instead of BPMN commands
} Type guard
boolean isBpmnScoped(ExternalWorkerJob job) {
return job.getProcessInstanceId() != null;
} Prevention
- Check scopeType/processInstanceId before invoking BPMN-specific job commands
- Separate BPMN and CMMN job handling in the worker client
- Filter the acquisition query to BPMN-scoped jobs only
When it happens
Trigger: Executing an AcquireExternalWorkerJobsCmd-derived command such as CompleteExternalWorkerJobCmd or BpmnExternalWorkerJobCmd (complete/fail/release via JobService/ExternalWorkerJobAcquireService) passing the id of a job created by a CMMN case, not a BPMN process.
Common situations: A generic external worker client acquires jobs from both process and case engines and, without checking scope, calls the BPMN completion API with a CMMN-scoped job id; job ids cached from a previous mixed-scope acquisition.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Can only complete BPMN external job with a BPMN error. Job…
- Can only terminate CMMN external job. Job with id
- at least one of userId or groups must be provided
- BPMN XSD could not be found
- Cannot combine onlyBpmn() with onlyCmmn() in the same query
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/9927520715099cba.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/AbstractExternalWorkerJobCmd.java:50
* @author Filip Hrisafov
*/
public abstract class AbstractExternalWorkerJobCmd implements Command<Void> {
protected final String externalJobId;
protected final String workerId;
protected final JobServiceConfiguration jobServiceConfiguration;
protected AbstractExternalWorkerJobCmd(String externalJobId, String workerId, JobServiceConfiguration jobServiceConfiguration) {
this.externalJobId = externalJobId;
this.workerId = workerId;
this.jobServiceConfiguration = jobServiceConfiguration;
}
@Override
public final Void execute(CommandContext commandContext) {
ExternalWorkerJobEntity externalWorkerJob = resolveJob(commandContext);
if (externalWorkerJob.getProcessInstanceId() == null) {
throw new FlowableException(externalWorkerJob + " is not bpmn scoped. This command can only handle bpmn scoped external worker jobs");
}
runJobLogic(externalWorkerJob, commandContext);
if (externalWorkerJob.isExclusive()) {
// Part of the same transaction to avoid a race condition with the
// potentially new jobs (wrt process instance locking) that are created
// during the execution of the original job
new UnlockExclusiveJobCmd(externalWorkerJob, jobServiceConfiguration).execute(commandContext);
}
return null;
}
protected abstract void runJobLogic(ExternalWorkerJobEntity externalWorkerJob, CommandContext commandContext);
protected void moveExternalWorkerJobToExecutableJob(ExternalWorkerJobEntity externalWorkerJob, CommandContext commandContext) {
jobServiceConfiguration.getJobManager().moveExternalWorkerJobToExecutableJob(externalWorkerJob);
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);View on GitHub (pinned to d6d39ce1c6)