karatelabs/karate · error · JsErrorException
Map.prototype.forEach: callback is not a function
Error message
Map.prototype.forEach: callback is not a function
What it means
ES Map.prototype.forEach compliance check: the first argument must be a callable callback that receives (value, key, map), but it was absent or not a function. Fix by passing an actual function to Map.prototype.forEach.
Solutions
- Pass an actual function: `map.forEach((v, k) => {...})`
- Check spelling of the callback variable before the call
- Replace non-function placeholders with a no-op `() => {}` if iteration is intentionally skipped
- Validate the callback exists when it comes from dynamic code
Example fix
// before
map.forEach('logEach'); // TypeError: callback is not a function
// after
map.forEach((v, k) => karate.log(k, v)); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof cb !== 'function') { throw new Error('forEach needs a function callback'); } Type guard
function isFn(x) { return typeof x === 'function'; } Try / catch
try {
m.forEach(cb);
} catch (e) {
if (String(e.message).includes('callback is not a function')) {
m.forEach(() => {}); // or surface a clear config error
} else throw e;
} Prevention
- Verify callback variables resolve to functions (check for typos)
- Don't pass callback name strings where functions are expected
- Use map.forEach((v, k) => ...) with an explicit function literal
When it happens
Trigger: `map.forEach()` with no args; `map.forEach(undefined)`; passing a string/number/object instead of a function; a misspelled function name evaluating to undefined (`map.forEach(callbac)`).
Common situations: Typos in callback names; leaving placeholder args during refactor; passing config values (like a callback name string from JSON) instead of actual functions.
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
- groupBy callback is not a function
- Constructor Map requires 'new'
- Map.prototype.set is not callable
- Iterator value is not an entry object
- Method Map.prototype called on incompatible receiver
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/488c0d190a1e0561.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsMapPrototype.java:99
}
private Object has(Context context, Object[] args) {
return asMap(context).hasKey(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
private Object delete(Context context, Object[] args) {
return asMap(context).deleteKey(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
private Object clear(Context context, Object[] args) {
asMap(context).clearAll();
return Terms.UNDEFINED;
}
private Object forEach(Context context, Object[] args) {
JsMap m = asMap(context);
if (args.length == 0 || !(args[0] instanceof JsCallable cb)) {
throw JsErrorException.typeError("Map.prototype.forEach: callback is not a function");
}
// Spec: forEach walks the live entry list. Entries appended during iteration
// are visited; deletions ahead of the cursor are skipped naturally because the
// cursor advances past them.
int cursor = 0;
while (cursor < m.entries.size()) {
Iterator<Map.Entry<Object, Object>> it = m.entries.entrySet().iterator();
for (int i = 0; i < cursor && it.hasNext(); i++) it.next();
if (!it.hasNext()) break;
Map.Entry<Object, Object> e = it.next();
cb.call(context, new Object[]{e.getValue(), e.getKey(), m});
cursor++;
}
return Terms.UNDEFINED;
}
private Object keys(Context context, Object[] args) {
JsMap m = asMap(context);View on GitHub (pinned to a22eb90246)