Activiti/Activiti · error · IllegalStateException

Variable does not exist

Error message

Variable does not exist

What it means

Thrown by TaskRuntimeHelper.assertVariableExists when updating a task variable and the task's local variable map is null — i.e. the task has no local variables at all. The runtime requires the variable to already exist before update; there is no upsert. This is the 'task has zero local variables' branch of the same assertion.

Solutions

  1. Create the variable first with createVariable, then update it.
  2. Verify the taskId is correct and that variables were created task-locally.
  3. Catch IllegalStateException and fall back to createVariable.

Example fix

// before
taskRuntime.updateVariable(TaskPayloadBuilder.updateVariable().withTaskId(taskId).withVariable(name, value).build());
// after
boolean exists = taskRuntime.variables(taskId).stream().anyMatch(v -> v.getName().equals(name));
if (exists) {
    taskRuntime.updateVariable(TaskPayloadBuilder.updateVariable().withTaskId(taskId).withVariable(name, value).build());
} else {
    taskRuntime.createVariable(TaskPayloadBuilder.createVariable().withTaskId(taskId).withVariable(name, value).build());
}
Defensive patterns

Strategy: validation

Validate before calling

boolean hasVariables = !taskRuntime.variables(taskId).isEmpty();
boolean exists = hasVariables && taskRuntime.variables(taskId).stream()
    .anyMatch(v -> v.getName().equals(name));
if (!exists) {
    taskRuntime.createVariable(TaskPayloadBuilder.createVariable().withTaskId(taskId).withVariable(name, value).build());
}

Try / catch

try {
    taskRuntime.updateVariable(payload);
} catch (IllegalStateException e) {
    if ("Variable does not exist".equals(e.getMessage())) {
        taskRuntime.createVariable(createPayload);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling TaskRuntime.updateVariable(UpdateTaskVariablePayload) for a taskId whose taskService.getVariableInstancesLocal(taskId) returns null (no local variables).

Common situations: Updating a variable on a fresh task that never had variables created; wrong taskId; variable was created on the process scope, not task-local scope; variable was deleted earlier.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/0b4fcaa223014894. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core/activiti-api-impl/activiti-api-task-runtime-impl/src/main/java/org/activiti/runtime/api/impl/TaskRuntimeHelper.java:287

        taskVariablesValidator.handleUpdateTaskVariablePayload(updateTaskVariablePayload);

        assertVariableExists(updateTaskVariablePayload);

        taskService.setVariableLocal(
            updateTaskVariablePayload.getTaskId(),
            updateTaskVariablePayload.getName(),
            updateTaskVariablePayload.getValue()
        );
    }

    private void assertVariableExists(UpdateTaskVariablePayload updateTaskVariablePayload) {
        Map<String, VariableInstance> variables = taskService.getVariableInstancesLocal(
            updateTaskVariablePayload.getTaskId()
        );

        if (variables == null) {
            throw new IllegalStateException("Variable does not exist");
        }

        if (!variables.containsKey(updateTaskVariablePayload.getName())) {
            throw new IllegalStateException("Variable does not exist");
        }
    }

    public void handleCompleteTaskPayload(CompleteTaskPayload completeTaskPayload) {
        completeTaskPayload.setVariables(
            taskVariablesValidator.handlePayloadVariables(completeTaskPayload.getVariables())
        );
    }

    public void handleSaveTaskPayload(SaveTaskPayload saveTaskPayload) {
        saveTaskPayload.setVariables(taskVariablesValidator.handlePayloadVariables(saveTaskPayload.getVariables()));
    }
}

View on GitHub (pinned to 56435b1a97)