flowable/flowable-engine · error · FlowableIllegalArgumentException

taskId is null

Error message

taskId is null

What it means

HasTaskVariableCmd.execute throws FlowableIllegalArgumentException when taskId is null. The command delegates variable lookup to the task service, which requires a concrete task id; a null id is rejected before the task is fetched.

Source

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

 */
public class HasTaskVariableCmd implements Command<Boolean>, Serializable {

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

    public HasTaskVariableCmd(String taskId, String variableName, boolean isLocal) {
        this.taskId = taskId;
        this.variableName = variableName;
        this.isLocal = isLocal;
    }

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

        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
        TaskEntity task = cmmnEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);

        if (task == null) {
            throw new FlowableObjectNotFoundException("task " + taskId + " doesn't exist", Task.class);
        }
        boolean hasVariable = false;

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

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure the task id is populated (persist/fetch the Task first) before calling
  2. Guard the call site with a null check on taskId
  3. Resolve the task via a TaskQuery and handle no-match before reading variables

Example fix

// before
boolean has = taskService.hasVariable(taskId, "priority");
// after
if (taskId != null) {
    boolean has = taskService.hasVariable(taskId, "priority");
}
Defensive patterns

Strategy: validation

Validate before calling

if (taskId == null) {
    throw new IllegalArgumentException("taskId is required for hasVariable");
}

Type guard

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

Try / catch

try {
    return taskService.hasVariable(taskId, variableName);
} catch (FlowableIllegalArgumentException e) {
    log.warn("Invalid hasVariable args: {}", e.getMessage());
    return false;
}

Prevention

When it happens

Trigger: Calling cmmnTaskService.hasVariable(null, variableName) or hasVariableLocal(null, variableName), or constructing the command with a null taskId (e.g. from a Task object that was never assigned an id).

Common situations: Task id obtained from a listener before the task entity was persisted, an uninitialized field in custom command code, or upstream query returning null task.

Related errors


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