flowable/flowable-engine · error · FlowableIllegalArgumentException

executionId is null

Error message

executionId is null

What it means

GetExecutionVariableCmd.execute() rejects a null executionId with FlowableIllegalArgumentException before any lookup. A variable cannot be read without identifying an execution, so null is treated as a programming/caller error.

Solutions

  1. Null-check the executionId before calling the runtime service.
  2. Resolve the execution first via a query and use Objects.requireNonNull on its id.
  3. At API boundaries return 400-level validation errors when the execution id parameter is missing.
  4. Fail fast in calling code with a descriptive exception instead of letting the engine throw.

Example fix

// before
Object value = runtimeService.getVariable(executionId, name);
// after
if (executionId != null) {
    Object value = runtimeService.getVariable(executionId, name);
}
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

try {
    runtimeService.getVariable(executionId, name);
} catch (FlowableIllegalArgumentException e) {
    // null executionId: fix caller, never expected at runtime
}

Prevention

When it happens

Trigger: Calling RuntimeService.getVariable(executionId, variableName) or getVariableLocal with executionId == null, typically from unguarded code paths where the execution reference was never resolved.

Common situations: A prior executionQuery returned null and its id was passed on; map/DTO fields not populated; conditional code skipping assignment.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/GetExecutionVariableCmd.java:47

 * @author Joram Barrez
 */
public class GetExecutionVariableCmd implements Command<Object>, Serializable {

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

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

    @Override
    public Object 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);
        }

        if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, execution.getProcessDefinitionId())) {
            Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
            return compatibilityHandler.getExecutionVariable(executionId, variableName, isLocal);
        }

        Object value;

View on GitHub (pinned to d6d39ce1c6)