flowable/flowable-engine · error · FlowableIllegalArgumentException
Job {jobId} parent is not CMMN case
Error message
Job {jobId} parent is not CMMN case What it means
Thrown by DefaultCmmnJobParentStateResolver.isSuspended when a job's scopeType is not 'cmmn' or its scopeId is empty, i.e. the job's parent is not a CMMN case instance. This resolver only knows how to determine suspension state via a CMMN case instance, so non-CMMN jobs are rejected with FlowableIllegalArgumentException.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/DefaultCmmnJobParentStateResolver.java:36
import org.flowable.common.engine.api.FlowableIllegalArgumentException;
import org.flowable.common.engine.api.scope.ScopeTypes;
import org.flowable.job.api.Job;
import org.flowable.job.service.InternalJobParentStateResolver;
/**
* @author martin.grofcik
*/
public class DefaultCmmnJobParentStateResolver implements InternalJobParentStateResolver {
private CmmnEngineConfiguration cmmnEngineConfiguration;
public DefaultCmmnJobParentStateResolver(CmmnEngineConfiguration cmmnEngineConfiguration) {
this.cmmnEngineConfiguration = cmmnEngineConfiguration;
}
@Override
public boolean isSuspended(Job job) {
if (!ScopeTypes.CMMN.equals(job.getScopeType()) || StringUtils.isEmpty(job.getScopeId())) {
throw new FlowableIllegalArgumentException("Job "+ job.getId() +" parent is not CMMN case");
}
CaseInstance caseInstance = this.cmmnEngineConfiguration.cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(job.getScopeId()).singleResult();
return CaseInstanceState.SUSPENDED.equals(caseInstance.getState());
}
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Ensure only CMMN-scoped jobs are routed to this resolver (register per-scope resolvers correctly)
- Check the job row in the DB: ACT_RU_JOB.SCOPE_TYPE_ should be 'cmmn' and SCOPE_ID_ set to the case instance id
- Re-create or repair jobs missing scopeType/scopeId after migrations
- If the job legitimately belongs to another engine, use that engine's resolver instead
Example fix
// before
boolean suspended = defaultCmmnJobParentStateResolver.isSuspended(job); // job scopeType=bpmn
// after
if (ScopeTypes.CMMN.equals(job.getScopeType()) && job.getScopeId() != null) {
boolean suspended = defaultCmmnJobParentStateResolver.isSuspended(job);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!"cmmn".equals(job.getScopeType()) || job.getScopeId() == null || job.getScopeId().isEmpty()) { /* route to correct resolver */ } Type guard
boolean isCmmnJob(Job job) { return "cmmn".equals(job.getScopeType()) && job.getScopeId() != null && !job.getScopeId().isEmpty(); } Try / catch
try { return resolver.isSuspended(job); } catch (FlowableIllegalArgumentException e) { log.warn("non-CMMN job {}: route to correct resolver", job.getId()); return false; } Prevention
- Register scope-specific suspension resolvers instead of one global resolver
- Validate job scopeType/scopeId columns after data migrations
- Only feed CMMN-scoped jobs to CMMN services
When it happens
Trigger: Job service invoking a registered suspension-state resolver for a job whose scopeType is not ScopeTypes.CMMN (e.g. a BPMN/async-executor job) or whose scopeId is null/empty.
Common situations: Deploying the CMMN engine alongside other engines and letting DefaultCmmnJobParentStateResolver handle jobs it shouldn't; jobs created without scopeType/scopeId populated (data migration or older data); misconfigured job service resolver wiring.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Job id is null
- Must specify a case definition tenant id to migrate
- Null task id
- type is required when adding a new task identity link
- userId and groupId cannot both be null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f70b5f92db4c8c3a.
Report an issue: GitHub.