flowable/flowable-engine · error · FlowableIllegalArgumentException

Unsupported variable query operation

Error message

Unsupported variable query operation: ${operation}

What it means

The switch over QueryVariableOperation has no case for the given operation, so it falls into the default branch and throws FlowableIllegalArgumentException. This occurs when the REST layer receives an operation value that the plan-item-instance query builder does not handle, typically an unrecognized/unsupported enum value.

Solutions

  1. Use one of the supported operations: EQUALS, NOT_EQUALS, EQUALS_IGNORECASE, NOT_EQUALS_IGNORECASE, GREATER_THAN, GREATER_THAN_OR_EQUALS, LESS_THAN, LESS_THAN_OR_EQUALS, LIKE (as handled by the switch).
  2. Remove EXISTS/NOT_EXISTS filters on this endpoint or switch to the task query endpoint that supports them.
  3. Verify the server version supports the operation you send.
  4. Catch the 400 response and print the unsupported operation from the message body.

Example fix

// before
{"name":"assignee","variableOperation":"exists","value":"x"}
// after
{"name":"assignee","variableOperation":"equals","value":"x"}
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = ['equals','notEquals','equalsIgnoreCase','notEqualsIgnoreCase','greaterThan','greaterThanOrEquals','lessThan','lessThanOrEquals','like'];
if (!filters.every(f => SUPPORTED.includes(f.variableOperation))) throw new Error('Unsupported variable operation for plan item instance query');

Type guard

const isSupportedOp = (op) => ['equals','notEquals','equalsIgnoreCase','notEqualsIgnoreCase','greaterThan','greaterThanOrEquals','lessThan','lessThanOrEquals','like'].includes(op);

Try / catch

try { await query(body); } catch (e) { if (e.status === 400 && /Unsupported variable query operation/.test(e.message)) { /* report allowed ops */ } else { throw e; } }

Prevention

When it happens

Trigger: Sending variableOperation values not handled by the switch (e.g. EXISTS / NOT_EXISTS which are supported on the task query but not here, or any misspelled/unknown operation string).

Common situations: Reusing task-query request payloads against the plan-item-instance endpoint; typos in the operation name; client SDK versions newer than the server (operation exists client-side but unsupported server-side).

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/planitem/PlanItemInstanceBaseResource.java:216

                    planItemInstanceQuery.caseVariableValueNotEquals(variable.getName(), actualValue);
                } else {
                    planItemInstanceQuery.variableValueNotEquals(variable.getName(), actualValue);
                }
                break;

            case NOT_EQUALS_IGNORE_CASE:
                if (actualValue instanceof String) {
                    if (isCase) {
                        planItemInstanceQuery.caseVariableValueNotEqualsIgnoreCase(variable.getName(), (String) actualValue);
                    } else {
                        planItemInstanceQuery.variableValueNotEqualsIgnoreCase(variable.getName(), (String) actualValue);
                    }
                } else {
                    throw new FlowableIllegalArgumentException("Only string variable values are supported when ignoring casing, but was: " + actualValue.getClass().getName());
                }
                break;
            default:
                throw new FlowableIllegalArgumentException("Unsupported variable query operation: " + variable.getVariableOperation());
            }
        }
    }

    protected PlanItemInstance getPlanItemInstanceFromRequest(String planItemInstanceId) {
        PlanItemInstance planItemInstance = runtimeService.createPlanItemInstanceQuery().planItemInstanceId(planItemInstanceId).includeEnded().singleResult();
        if (planItemInstance == null) {
            throw new FlowableObjectNotFoundException("Could not find an plan item instance with id '" + planItemInstanceId + "'.", PlanItemInstance.class);
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessPlanItemInstanceInfoById(planItemInstance);
        }
        
        return planItemInstance;
    }

    protected Map<String, Object> getVariablesToSet(List<RestVariable> restVariables) {

View on GitHub (pinned to d6d39ce1c6)