{"record":{"id":"06af33520d4704f1","repo":"flowable/flowable-engine","slug":"the-input-should-always-be-even-since-we-expect-a-06af33","errorCode":null,"errorMessage":"The input should always be even since we expect a list of key-value pairs!","messagePattern":"The input should always be even since we expect a list of key-value pairs!","errorType":"validation","errorClass":"org.activiti.engine.ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/util/CollectionUtil.java","lineNumber":50,"sourceCode":"     * Helper method that creates a singleton map.\n     * <p>\n     * 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.\n     */\n    public static Map<String, Object> singletonMap(String key, Object value) {\n        Map<String, Object> map = new HashMap<>();\n        map.put(key, value);\n        return map;\n    }\n\n    /**\n     * Helper method to easily create a map.\n     * <p>\n     * Takes as input a varargs containing the key1, value1, key2, value2, etc. Note: although an Object, we will cast the key to String internally.\n     */\n    public static Map<String, Object> map(Object... objects) {\n\n        if (objects.length % 2 != 0) {\n            throw new ActivitiIllegalArgumentException(\"The input should always be even since we expect a list of key-value pairs!\");\n        }\n\n        Map<String, Object> map = new HashMap<>();\n        for (int i = 0; i < objects.length; i += 2) {\n            map.put((String) objects[i], objects[i + 1]);\n        }\n\n        return map;\n    }\n\n}\n","sourceCodeStart":32,"sourceCodeEnd":62,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/util/CollectionUtil.java#L32-L62","documentation":"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.","triggerScenarios":"Calling CollectionUtil.map with an odd number of arguments, e.g. map(\"a\", 1, \"b\") — often from dynamically assembled argument arrays.","commonSituations":"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.","solutions":["Audit the call site so every key has a matching value; count arguments at compile time where possible.","When pairs are added conditionally, build the map explicitly with Map.put instead of varargs.","Validate the array length is even before invoking map()."],"exampleFix":"// before\nMap<String,Object> vars = CollectionUtil.map(\"a\", 1, \"b\");\n// after\nMap<String,Object> vars = CollectionUtil.map(\"a\", 1, \"b\", 2);","handlingStrategy":"validation","validationCode":"if ((objects.length & 1) != 0) throw new IllegalArgumentException(\"map() requires an even number of key/value arguments\");","typeGuard":null,"tryCatchPattern":"try {\n    Map<String,Object> vars = CollectionUtil.map(pairs);\n} catch (ActivitiIllegalArgumentException e) {\n    if (e.getMessage().contains(\"input should always be even\")) { /* rebuild pairs */ }\n}","preventionTips":["Prefer explicit Map.put chains over varargs when pairs are built conditionally","Keep key/value pairs adjacent in code and reviewed together","Use a single constant array of pairs rather than literals scattered across code"],"tags":["collections","argument-count","utility"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}