flowable/flowable-engine · error · FlowableObjectNotFoundException
Task '
Error message
Task '
What it means
When reading a task variable via the CMMN REST API, if the variable is not found in the requested scope (global or local) the API throws FlowableObjectNotFoundException (HTTP 404) naming the task id and variable name. This distinguishes 'task exists but variable absent' from other errors.
Source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskVariableBaseResource.java:102
variableFound = true;
}
}
} else if (variableScope == RestVariableScope.GLOBAL) {
if (ScopeTypes.CMMN.equals(task.getScopeType()) && task.getScopeId() != null && runtimeService.hasVariable(task.getScopeId(), variableName)) {
value = runtimeService.getVariable(task.getScopeId(), variableName);
variableFound = true;
}
} else if (variableScope == RestVariableScope.LOCAL) {
if (taskService.hasVariableLocal(taskId, variableName)) {
value = taskService.getVariableLocal(taskId, variableName);
variableFound = true;
}
}
if (!variableFound) {
throw new FlowableObjectNotFoundException("Task '" + taskId + "' doesn't have a variable with name: '" + variableName + "'.", VariableInstanceEntity.class);
} else {
return restResponseFactory.createRestVariable(variableName, value, variableScope, taskId, CmmnRestResponseFactory.VARIABLE_TASK, includeBinary);
}
}
protected boolean hasVariableOnScope(Task task, String variableName, RestVariableScope scope) {
boolean variableFound = false;
if (scope == RestVariableScope.GLOBAL) {
if (ScopeTypes.CMMN.equals(task.getScopeType()) && task.getScopeId() != null && runtimeService.hasVariable(task.getScopeId(), variableName)) {
variableFound = true;
}
} else if (scope == RestVariableScope.LOCAL) {
if (taskService.hasVariableLocal(task.getId(), variableName)) {
variableFound = true;
}
}View on GitHub (pinned to d6d39ce1c6)
Solutions
- Check available names first via GET /cmmn-runtime/tasks/{taskId}/variables.
- Add scope qualifier: use /variables/{name}/local for local variables.
- Handle 404 gracefully with a default value in the client.
- Fix the variable name spelling or set the variable before reading it.
Example fix
// before GET /cmmn-runtime/tasks/123/variables/approvl // 404 // after GET /cmmn-runtime/tasks/123/variables/approval // correct name GET /cmmn-runtime/tasks/123/variables/approval/local // if local-scoped
Defensive patterns
Strategy: try-catch
Validate before calling
const all = await api.get(`/cmmn-runtime/tasks/${taskId}/variables`);
const exists = all.some(v => v.name === variableName); Try / catch
try { return await api.get(`/cmmn-runtime/tasks/${taskId}/variables/${name}`); } catch (e) { if (e.response && e.response.status === 404) return defaultValue; throw e; } Prevention
- List task variables before reading a specific one
- Use the correct /local scope path for local variables
- Centralize variable name constants to avoid typos
When it happens
Trigger: GET /cmmn-runtime/tasks/{taskId}/variables/{variableName} (or scoped variants) where the variable name never existed on the task, was set only in the other scope, or was deleted.
Common situations: Typos in variable names; querying a local-only variable without /local and vice versa; reading after task completion removed runtime variables; case/prefix mismatch between services.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Plan item instance '${id}' does not have a variable '${varia
- plan item instance ${planItemInstanceId} doesn't exist
- plan item instance ${planItemInstanceId} doesn't exist
- No plan item instance found for id
- No case instance found for id ${caseInstanceId}
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/6c4b538f113c3a7b.
Report an issue: GitHub.