flowable/flowable-engine · error · FlowableIllegalArgumentException

Variable value is missing for variable:

Error message

Variable value is missing for variable: 

What it means

FlowableIllegalArgumentException thrown by addVariables when a QueryVariable entry has an operation but its value is null. A null value cannot be compared, and value-less comparisons (e.g. EXISTS) are not supported by this endpoint, so the request is rejected as invalid.

Source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/history/HistoricVariableInstanceBaseResource.java:105

        if (queryRequest.getVariables() != null) {
            addVariables(query, queryRequest.getVariables());
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessHistoryVariableInfoWithQuery(query, queryRequest);
        }

        return paginateList(allRequestParams, queryRequest, query, "variableName", allowedSortProperties,
                restResponseFactory::createHistoricVariableInstanceResponseList);
    }

    protected void addVariables(HistoricVariableInstanceQuery variableInstanceQuery, List<QueryVariable> variables) {
        for (QueryVariable variable : variables) {
            if (variable.getVariableOperation() == null) {
                throw new FlowableIllegalArgumentException("Variable operation is missing for variable: " + variable.getName());
            }
            if (variable.getValue() == null) {
                throw new FlowableIllegalArgumentException("Variable value is missing for variable: " + variable.getName());
            }

            boolean nameLess = variable.getName() == null;

            Object actualValue = restResponseFactory.getVariableValue(variable);

            // A value-only query is only possible using equals-operator
            if (nameLess) {
                throw new FlowableIllegalArgumentException("Value-only query (without a variable-name) is not supported");
            }

            switch (variable.getVariableOperation()) {

            case EQUALS:
                variableInstanceQuery.variableValueEquals(variable.getName(), actualValue);
                break;

            default:

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Provide a concrete value: variables=[{"name":"status","operation":"EQUALS","value":"active"}]
  2. Skip the variable entry entirely when the value is empty instead of sending it with null
  3. Convert empty user input to a sentinel or drop the clause before building the query
  4. If you need to match unset variables, this endpoint cannot express it — fetch instances and filter client-side or use a different query API

Example fix

// before
const filter = {name: 'status', operation: 'EQUALS', value: userInput.value}
// after
const clauses = [];
if (userInput.value !== '' && userInput.value != null) {
  clauses.push({name: 'status', operation: 'EQUALS', value: userInput.value});
}
const qs = clauses.length ? '?variables=' + encodeURIComponent(JSON.stringify(clauses)) : '';
Defensive patterns

Strategy: validation

Validate before calling

const valid = clauses.filter(c => c.value !== null && c.value !== undefined && c.value !== '');
const qs = valid.length ? '?variables=' + encodeURIComponent(JSON.stringify(valid)) : '';

Type guard

function hasValue(c) { return c !== null && c !== undefined && c.value !== null && c.value !== undefined && c.value !== ''; }

Try / catch

try { return await queryHistoricVariables(clauses); } catch (e) { if (String(e.message).includes('value is missing')) { clauses = clauses.filter(hasValue); return queryHistoricVariables(clauses); } throw e; }

Prevention

When it happens

Trigger: GET/POST /history/historic-variable-instances with variables=[{"name":"status","operation":"EQUALS","value":null}] — the value key is absent or explicitly null; a JSON body that serializes Java null because the client left the filter input empty.

Common situations: Dynamic filter forms where the user left the value field blank but the operation was chosen; serialization frameworks dropping empty strings; API consumers who intended a null-comparison which this endpoint does not support.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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