flowable/flowable-engine · error · FlowableIllegalArgumentException

caseInstanceId is null

Error message

caseInstanceId is null

What it means

GetVariableCmd.execute() retrieves a case-instance variable and first validates the caseInstanceId. A null caseInstanceId throws FlowableIllegalArgumentException('caseInstanceId is null') because variables are scoped to a case instance and cannot be resolved without it.

Source

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

import org.flowable.variable.service.impl.persistence.entity.VariableInstanceEntity;

/**
 * @author Joram Barrez
 */
public class GetVariableCmd implements Command<Object> {
    
    protected String caseInstanceId;
    protected String variableName;
    
    public GetVariableCmd(String caseInstanceId, String variableName) {
        this.caseInstanceId = caseInstanceId;
        this.variableName = variableName;
    }
    
    @Override
    public Object execute(CommandContext commandContext) {
        if (caseInstanceId == null) {
            throw new FlowableIllegalArgumentException("caseInstanceId is null");
        }

        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);

        // In the BPMN engine, this is done by getting the variable on the execution.
        // However, doing the same in CMMN will fetch the case instance and non-completed plan item instances in one query.
        // Hence, why here a direct query is done here (which is cached).
        VariableInstanceEntity variableInstanceEntity = cmmnEngineConfiguration.getVariableServiceConfiguration().getVariableService()
                .createInternalVariableInstanceQuery()
                .scopeId(caseInstanceId)
                .withoutSubScopeId()
                .scopeType(ScopeTypes.CMMN)
                .name(variableName)
                .singleResult();
        if (variableInstanceEntity != null) {
            return variableInstanceEntity.getValue();
        }
        return null;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Null-check caseInstanceId before calling cmmnRuntimeService.getVariable/getVariableLocal.
  2. Capture the case instance id returned by cmmnRuntimeService.startCaseInstance(...) and use it directly.
  3. If the case id comes from another query, verify that query returned a non-null result first.
  4. Ensure execution scoped to the case (listener, delegate) correctly carries the case instance id.

Example fix

// before
Object value = cmmnRuntimeService.getVariable(caseInstanceId, "approvalStatus");
// after
if (caseInstanceId == null) {
    throw new IllegalStateException("caseInstanceId not set - start or resolve the case first");
}
Object value = cmmnRuntimeService.getVariable(caseInstanceId, "approvalStatus");
Defensive patterns

Strategy: validation

Validate before calling

if (caseInstanceId == null) { throw new IllegalArgumentException("caseInstanceId is required"); }

Type guard

boolean hasCaseInstance(String caseInstanceId) { return caseInstanceId != null && !caseInstanceId.isEmpty(); }

Try / catch

try { return runtimeService.getVariable(caseInstanceId, name); } catch (FlowableIllegalArgumentException e) { log.error("Missing caseInstanceId: {}", e.getMessage()); throw e; }

Prevention

When it happens

Trigger: Calling cmmnRuntimeService.getVariable(null, variableName) or getVariableLocal(null, name); constructing GetVariableCmd(null, name) and executing it; caseInstanceId taken from an unset process context.

Common situations: Case id stored in an application-side variable that was never populated after case start; null return from a prior getCaseInstance query reused as the id; message/correlation handler that failed to resolve the case before fetching variables.

Related errors


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