karatelabs/karate · error · RuntimeException

forEach() needs two arguments: collection and function

Error message

forEach() needs two arguments: collection and function

What it means

Arity guard in the karate.forEach() JS utility: it needs exactly the collection to iterate and the callback function to apply to each element. Fires when forEach() is called with fewer than two arguments; supply both the collection and the function.

Solutions

  1. Pass the callback: forEach(list, function(v, i){ ... })
  2. Ensure the first argument is a List or Map
  3. Use the native JS list.forEach(fn) form if iterating plain JS arrays

Example fix

// before
karate.forEach(items);
// after
karate.forEach(items, function(item, i){ karate.log(item, i); });
Defensive patterns

Strategy: type-guard

Validate before calling

if (!collection || typeof fn !== 'function') throw new Error('forEach requires a collection and a function');

Type guard

function canForEach(args) { return args.length >= 2 && args[0] != null && typeof args[1] === 'function'; }

Try / catch

try { karate.forEach(items, fn); } catch (e) { karate.log('forEach failed: ' + e.message); }

Prevention

When it happens

Trigger: Calling forEach(list) without the callback, forEach() empty, or passing something non-callable as the second argument.

Common situations: Confusing forEach with Array.prototype.forEach method-call style (list.forEach(fn)) when using the karate.* helper; forgetting the callback during refactors; passing a config object instead of a function.

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 karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/dd7199367e170a69. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/KarateJsUtils.java:241

                }
            } else {
                // filterKeys(source, key1, key2, ...)
                for (int i = 1; i < args.length; i++) {
                    String key = args[i].toString();
                    if (source.containsKey(key)) {
                        result.put(key, source.get(key));
                    }
                }
            }
            return result;
        };
    }

    @SuppressWarnings("unchecked")
    static JavaInvokable forEach() {
        return args -> {
            if (args.length < 2) {
                throw new RuntimeException("forEach() needs two arguments: collection and function");
            }
            Object collection = args[0];
            JavaCallable fn = (JavaCallable) args[1];
            if (collection instanceof List<?> list) {
                for (int i = 0; i < list.size(); i++) {
                    fn.call(null, new Object[]{list.get(i), i});
                }
            } else if (collection instanceof Map) {
                Map<String, Object> map = (Map<String, Object>) collection;
                int i = 0;
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    fn.call(null, new Object[]{entry.getKey(), entry.getValue(), i++});
                }
            }
            return null;
        };
    }

View on GitHub (pinned to a22eb90246)