flowable/flowable-engine · error · FlowableIllegalArgumentException

Can only complete a stage plan item instance that is marked

Error message

Can only complete a stage plan item instance that is marked as completable (there might still be active plan item instance).

What it means

After the type check, CompleteStagePlanItemInstanceCmd verifies the stage is completable (no active child plan item instances) unless force=true. A stage still containing active plan items throws this FlowableIllegalArgumentException.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CompleteStagePlanItemInstanceCmd.java:54

        super(planItemInstanceId);
        this.force = force;
    }

    public CompleteStagePlanItemInstanceCmd(String planItemInstanceId, Map<String, Object> variables,
            Map<String, Object> formVariables, String formOutcome, FormInfo formInfo,
            Map<String, Object> localVariables, Map<String, Object> transientVariables, boolean force) {
        
        super(planItemInstanceId, variables, formVariables, formOutcome, formInfo, localVariables, transientVariables);
        this.force = force;
    }

    @Override
    protected void internalExecute(CommandContext commandContext, PlanItemInstanceEntity planItemInstanceEntity) {
        if (!PlanItemDefinitionType.STAGE.equals(planItemInstanceEntity.getPlanItemDefinitionType())) {
            throw new FlowableIllegalArgumentException("Can only complete plan item instances of type stage. Type is " + planItemInstanceEntity.getPlanItemDefinitionType());
        }
        if (!force && !planItemInstanceEntity.isCompletable()) { // if force is true, ignore the completable flag
            throw new FlowableIllegalArgumentException("Can only complete a stage plan item instance that is marked as completable (there might still be active plan item instance).");
        }
        CommandContextUtil.getAgenda(commandContext).planCompletePlanItemInstanceOperation(planItemInstanceEntity);
    }
    
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Complete or terminate all active child plan item instances within the stage first.
  2. Pass force=true to cmmnRuntimeService.completePlanItemInstance(planItemInstanceId, true) if the stage should be forcibly completed.
  3. Check children first: cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceParentId(stageId).stateActive().count().
  4. Adjust the case model's completion rules (auto-complete/requiring rules) if stages should close automatically.

Example fix

// before
cmmnRuntimeService.completePlanItemInstance(stageId, false); // stage has active children

// after
cmmnRuntimeService.completePlanItemInstance(stageId, true); // forced, or finish children first
Defensive patterns

Strategy: try-catch

Validate before calling

long activeChildren = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceParentId(stageId).stateActive().count();
boolean canComplete = activeChildren == 0;

Try / catch

try { cmmnRuntimeService.completePlanItemInstance(stageId, false); } catch (FlowableIllegalArgumentException e) { /* stage not completable; retry with force or finish children */ }

Prevention

When it happens

Trigger: Calling cmmnRuntimeService.completePlanItemInstance(stagePlanItemInstanceId, force=false) while the stage still has active child plan item instances, so planItemInstanceEntity.isCompletable() returns false.

Common situations: Trying to close a stage with unfinished human tasks inside; not passing the force flag in a cleanup/admin scenario; assuming completing the parent completes children.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/4f7cce22847a2975. Report an issue: GitHub.