flowable/flowable-engine · error · FlowableIllegalArgumentException

The input should always be even since we expect a list of ke

Error message

The input should always be even since we expect a list of key-value pairs!

What it means

CollectionUtil.map(Object...) builds a Map from alternating key/value varargs and throws FlowableIllegalArgumentException when the number of arguments is odd. Keys are cast to String, so an even count of pairs is required.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/util/CollectionUtil.java:55

     * Helper method that creates a singleton map.
     * 
     * Alternative for Collections.singletonMap(), since that method returns a generic typed map depending on the input type, but we often need a String, Object map.
     */
    public static Map<String, Object> singletonMap(String key, Object value) {
        Map<String, Object> map = new HashMap<>(1);
        map.put(key, value);
        return map;
    }

    /**
     * Helper method to easily create a map.
     * 
     * Takes as input a varargs containing the key1, value1, key2, value2, etc. Note: although an Object, we will cast the key to String internally.
     */
    public static Map<String, Object> map(Object... objects) {

        if (objects.length % 2 != 0) {
            throw new FlowableIllegalArgumentException("The input should always be even since we expect a list of key-value pairs!");
        }

        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < objects.length; i += 2) {
            map.put((String) objects[i], objects[i + 1]);
        }

        return map;
    }

    public static boolean isEmpty(@SuppressWarnings("rawtypes") Collection collection) {
        return (collection == null || collection.isEmpty());
    }

    public static boolean isNotEmpty(@SuppressWarnings("rawtypes") Collection collection) {
        return !isEmpty(collection);
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Count the arguments and add the missing key or value to make pairs complete
  2. Prefer building the map directly (new HashMap<>) or Map.of(...) instead of varargs
  3. Write a helper that asserts pairs at the call site before invoking map

Example fix

// before
CollectionUtil.map("orderId", orderId, "customerId");
// after
CollectionUtil.map("orderId", orderId, "customerId", customerId);
Defensive patterns

Strategy: validation

Validate before calling

if (args.length % 2 != 0) {
    throw new IllegalArgumentException("map() requires an even number of key/value arguments");
}

Try / catch

try {
    Map<String, Object> vars = CollectionUtil.map(args);
} catch (FlowableIllegalArgumentException e) {
    logger.error("Malformed key/value varargs: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling CollectionUtil.map("k1", v1, "k2") — a vararg list with an odd element count, usually from a manually edited or generated argument list.

Common situations: Hand-writing process-variable maps and forgetting a value; refactoring removed an entry; dynamic argument array assembled with a missing element.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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