flowable/flowable-engine · error · FlowableIllegalArgumentException

The variable value does not have a type

Error message

The variable value does not have a type

What it means

extractVariableValue resolves the concrete value of a query variable by looking up its 'type' among the engine's configured VariableTypes. If the variableValue JSON node has no 'type' field, the value cannot be deserialized and this FlowableIllegalArgumentException is thrown.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/delete/BatchDeleteProcessConfig.java:405

                        query.variableNotExists(variableName);
                        break;
                    case NOT_EQUALS_IGNORE_CASE:
                        //Not exposed on the public API
                        //query.variableValueNotEqualsIgnoreCase(variableName, (String) extractVariableValue(variableValue, engineConfiguration));
                        //break
                    default:
                        throw new FlowableIllegalArgumentException("Operator " + operator + " is not supported for the variable value");
                }
            }

        }

    }

    protected static Object extractVariableValue(JsonNode variableValueNode, ProcessEngineConfigurationImpl engineConfiguration) {
        String type = variableValueNode.path("type").stringValue(null);
        if (type == null) {
            throw new FlowableIllegalArgumentException("The variable value does not have a type");
        }

        VariableType variableType = engineConfiguration.getVariableTypes()
                .getVariableType(type);
        return variableType.getValue(new VariableValueJsonNodeValueFields(variableValueNode));
    }

    protected static List<String> asStringList(JsonNode node) {
        if (node != null && node.isArray() && !node.isEmpty()) {
            List<String> values = new ArrayList<>(node.size());
            for (JsonNode element : node) {
                values.add(element.stringValue());
            }
            return values;
        }

        return null;
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Add the required "type" field matching a registered variable type, e.g. "string", "long", "double", "date"
  2. Verify the type name exists in ProcessEngineConfiguration.getVariableTypes()
  3. Generate the batch configuration programmatically from a real HistoricProcessInstanceQuery so type metadata is preserved

Example fix

// before
{ "name": "amount", "operator": "EQUALS", "value": 5 }
// after
{ "name": "amount", "operator": "EQUALS", "type": "long", "value": 5 }
Defensive patterns

Strategy: validation

Validate before calling

for (JsonNode var : variableValuesJson) {
    if (var.path("type").stringValue(null) == null) {
        throw new IllegalArgumentException("variableValue missing type: " + var);
    }
}

Try / catch

try {
    config = BatchDeleteProcessConfig.create(partId, engineConfiguration);
} catch (FlowableIllegalArgumentException e) {
    logger.error("Variable value missing type: " + e.getMessage());
}

Prevention

When it happens

Trigger: A variableValue object in the batch configuration's variableValues array lacking the 'type' key, e.g. { "name": "amount", "operator": "EQUALS", "value": 5 }.

Common situations: Hand-written or hand-edited batch delete configurations; tooling exporting query variables without type metadata; users assuming the type can be inferred from the value.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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