flowable/flowable-engine · error · org.activiti.engine.ActivitiIllegalArgumentException

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

Error message

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

What it means

CollectionUtil.map builds a Map<String,Object> from varargs interpreted as alternating key/value pairs. An odd number of arguments means an unpaired value, so it throws ActivitiIllegalArgumentException before building the map.

Solutions

  1. Audit the call site so every key has a matching value; count arguments at compile time where possible.
  2. When pairs are added conditionally, build the map explicitly with Map.put instead of varargs.
  3. Validate the array length is even before invoking map().

Example fix

// before
Map<String,Object> vars = CollectionUtil.map("a", 1, "b");
// after
Map<String,Object> vars = CollectionUtil.map("a", 1, "b", 2);
Defensive patterns

Strategy: validation

Validate before calling

if ((objects.length & 1) != 0) throw new IllegalArgumentException("map() requires an even number of key/value arguments");

Try / catch

try {
    Map<String,Object> vars = CollectionUtil.map(pairs);
} catch (ActivitiIllegalArgumentException e) {
    if (e.getMessage().contains("input should always be even")) { /* rebuild pairs */ }
}

Prevention

When it happens

Trigger: Calling CollectionUtil.map with an odd number of arguments, e.g. map("a", 1, "b") — often from dynamically assembled argument arrays.

Common situations: Programmatic construction of process variables where one key/value pair is conditionally skipped but its counterpart isn't; refactoring that removed one element of a pair.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/util/CollectionUtil.java:50

     * Helper method that creates a singleton map.
     * <p>
     * Alternative for Collections.singletonMap(), since that method returns a generic typed map <K,T> 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<>();
        map.put(key, value);
        return map;
    }

    /**
     * Helper method to easily create a map.
     * <p>
     * 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 ActivitiIllegalArgumentException("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;
    }

}

View on GitHub (pinned to d6d39ce1c6)