flowable/flowable-engine · error · FlowableIllegalArgumentException

planItemInstanceId is null

Error message

planItemInstanceId is null

What it means

HasPlanItemInstanceVariableCmd.execute throws FlowableIllegalArgumentException when planItemInstanceId is null. The command requires both a plan item instance id and a variable name; without the id it cannot locate the plan item instance, so it fails fast before any database access.

Source

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

import org.flowable.common.engine.impl.interceptor.CommandContext;

/**
 * @author Christopher Welsch
 */
public class HasPlanItemInstanceVariableCmd implements Command<Boolean> {

    protected String planItemInstanceId;
    protected String variableName;

    public HasPlanItemInstanceVariableCmd(String caseInstanceId, String variableName) {
        this.planItemInstanceId = caseInstanceId;
        this.variableName = variableName;
    }

    @Override
    public Boolean execute(CommandContext commandContext) {
        if (planItemInstanceId == null) {
            throw new FlowableIllegalArgumentException("planItemInstanceId is null");
        }
        if (variableName == null) {
            throw new FlowableIllegalArgumentException("variableName is null");
        }

        PlanItemInstanceEntity planItemInstance = CommandContextUtil.getPlanItemInstanceEntityManager(commandContext).findById(planItemInstanceId);

        if (planItemInstance == null) {
            throw new FlowableObjectNotFoundException("plan item instance " + planItemInstanceId + " doesn't exist", PlanItemInstance.class);
        }
        return planItemInstance.hasVariableLocal(variableName);
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure the plan item instance id is captured from a valid PlanItemInstance before calling
  2. Guard the call with a null check on the id
  3. If deriving the id from a query, handle the null singleResult() case first

Example fix

// before
boolean has = cmmnRuntimeService.hasPlanItemVariable(planItemInstanceId, "flag");
// after
if (planItemInstanceId != null) {
    boolean has = cmmnRuntimeService.hasPlanItemVariable(planItemInstanceId, "flag");
}
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

boolean hasPlanItemInstanceId(String id) {
    return id != null && !id.isEmpty();
}

Try / catch

try {
    return cmmnRuntimeService.hasPlanItemVariable(planItemInstanceId, variableName);
} catch (FlowableIllegalArgumentException e) {
    log.warn("Invalid hasPlanItemVariable args: {}", e.getMessage());
    return false;
}

Prevention

When it happens

Trigger: Calling cmmnRuntimeService.hasPlanItemVariable(null, variableName) or the local variant, or constructing the command directly with a null id.

Common situations: Plan item id obtained from a listener/stage context that was null (e.g. evaluated outside an active plan item), an uninitialized variable in custom delegation code, or a lookup that returned no result upstream.

Related errors


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