flowable/flowable-engine · error · FlowableIllegalArgumentException

executionId is null

Error message

executionId is null

What it means

HasExecutionVariableCmd.execute() throws FlowableIllegalArgumentException("executionId is null") when the execution id argument is null. The command checks whether a variable exists on an execution, which requires a valid execution reference.

Solutions

  1. Pass a non-null executionId to runtimeService.hasVariable/hasVariableLocal.
  2. Resolve the executionId from a verified ExecutionEntity/ProcessInstance before checking variables.
  3. Fix the upstream lookup that yielded null (e.g. processInstanceId -> execution resolution).
  4. Catch FlowableIllegalArgumentException and return a 400-style validation error.

Example fix

// before
boolean has = runtimeService.hasVariable(ctx.getExecutionId(), "approved");
// after
if (ctx.getExecutionId() != null) {
    boolean has = runtimeService.hasVariable(ctx.getExecutionId(), "approved");
}
Defensive patterns

Strategy: validation

Validate before calling

if (executionId == null || executionId.isEmpty()) {
    throw new IllegalArgumentException("executionId must be provided");
}

Type guard

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

Try / catch

try {
    return runtimeService.hasVariable(executionId, variableName);
} catch (FlowableIllegalArgumentException e) {
    throw new BadRequestException("Invalid hasVariable arguments: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling runtimeService.hasVariable(null, variableName) / hasVariableLocal(null, name) — the runtime service builds HasExecutionVariableCmd with a null executionId.

Common situations: executionId taken from a process instance lookup that returned null; REST handler with a missing path parameter mapped to null; code path where the execution was conditionally resolved but the variable check ran unconditionally.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/HasExecutionVariableCmd.java:44

 * @author Frederik Heremans
 */
public class HasExecutionVariableCmd implements Command<Boolean>, Serializable {

    private static final long serialVersionUID = 1L;
    protected String executionId;
    protected String variableName;
    protected boolean isLocal;

    public HasExecutionVariableCmd(String executionId, String variableName, boolean isLocal) {
        this.executionId = executionId;
        this.variableName = variableName;
        this.isLocal = isLocal;
    }

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

        ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager(commandContext).findById(executionId);

        if (execution == null) {
            throw new FlowableObjectNotFoundException("execution " + executionId + " doesn't exist", Execution.class);
        }

        boolean hasVariable = false;

        if (isLocal) {
            hasVariable = execution.hasVariableLocal(variableName);
        } else {
            hasVariable = execution.hasVariable(variableName);
        }

View on GitHub (pinned to d6d39ce1c6)