flowable/flowable-engine · error · FlowableException

Include in stage overview expression does not resolve to a…

Error message

Include in stage overview expression does not resolve to a boolean value ${includeInStageOverview}: ${stageValueObject} for ${variableContainer}

What it means

GetStageOverviewCmd evaluates the stage's 'include in stage overview' expression and requires it to resolve to a java.lang.Boolean. Flowable throws FlowableException when the expression yields any other type (String, Integer, null), because the result is cast directly to Boolean.

Solutions

  1. Change the expression so it yields a boolean, e.g. ${includeFlag == 'true'} or ${booleanVar}
  2. Store the underlying case variable as a Boolean (caseService.setVariable(id, "includeFlag", true)) rather than a String
  3. Add a default: ${includeFlag != null && includeFlag == true} to guard against null
  4. Inspect the referenced variable in the running case instance to see its actual type

Example fix

// before (expression resolves to String)
<planItemDefinition ... flowable:includeInStageOverviewExpression="${includeFlag}"/>
// after
<planItemDefinition ... flowable:includeInStageOverviewExpression="${includeFlag == 'true'}"/>
Defensive patterns

Strategy: validation

Validate before calling

Object v = caseService.getVariable(caseInstanceId, "includeFlag");
if (!(v instanceof Boolean)) {
    throw new IllegalStateException("includeFlag must be a Boolean, got: " + (v == null ? "null" : v.getClass().getName()));
}

Type guard

boolean isBooleanExpressionValue(Object o) { return o instanceof Boolean; }

Try / catch

try {
    List<StageResponse> stages = cmmnRuntimeService.getStageOverview(caseInstanceId, null);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("Include in stage overview expression")) {
        // fix model expression / variable type
    }
}

Prevention

When it happens

Trigger: A stage plan item's includeInStageOverviewExpression (stage overview expression) evaluates against case variables and returns a non-Boolean, e.g. the expression references a String variable like ${includeFlag} where includeFlag='true'.

Common situations: Setting the expression to a variable holding the string 'true' instead of a boolean; expression resolving to null because the variable is missing; using an expression that returns a number or object.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

                // If not ended or current, it's implicitly a future one
                if (planItemInstance.isPresent()) {
                    stageResponse.setEndTime(planItemInstance.get().getEndedTime());
                    stageResponse.setEnded(stageResponse.getEndTime() != null);
                    stageResponse.setCurrent(PlanItemInstanceState.ACTIVE.equals(planItemInstance.get().getState()));
                }

                stageResponses.add(stageResponse);
            }
        }

        return stageResponses;
    }
    
    protected boolean evaluateIncludeInStageOverviewExpression(Expression stageExpression, String includeInStageOverview, VariableContainer variableContainer) {
        Object stageValueObject = stageExpression.getValue(variableContainer);
        if (!(stageValueObject instanceof Boolean)) {
            throw new FlowableException("Include in stage overview expression does not resolve to a boolean value " + 
                            includeInStageOverview + ": " + stageValueObject + " for " + variableContainer);
        }
        
        return (Boolean) stageValueObject;
    }
    
    protected Date getPlanItemInstanceEndTime(List<PlanItemInstance> planItemInstances, PlanItemDefinition planItemDefinition) {
        return getPlanItemInstance(planItemInstances, planItemDefinition)
            .map(PlanItemInstance::getEndedTime)
            .orElse(null);
    }

    protected Optional<PlanItemInstance> getPlanItemInstance(List<PlanItemInstance> planItemInstances, PlanItemDefinition planItemDefinition) {
        PlanItemInstance planItemInstance = null;
        for (PlanItemInstance p : planItemInstances) {
            if (p.getPlanItemDefinitionId().equals(planItemDefinition.getId())) {
                
                if (p.getEndedTime() == null) {

View on GitHub (pinned to d6d39ce1c6)