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
- Create the variable first with createVariable, then update it.
- Verify the taskId is correct and that variables were created task-locally.
- 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
- Verify the taskId points to the intended task before updating.
- Remember updates are not upserts: create first.
- Check whether variables live at task-local vs process scope.
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
- Variable already exists
- Provided process definition must have a deployment id.
- Provided process definition must have its resource name set.
- Set of taskIds is empty
- task doesn't exist
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)