karatelabs/karate · error · TypeError
Set.prototype.forEach: callback is not a function
Error message
Set.prototype.forEach: callback is not a function
What it means
Set.prototype.forEach requires its first argument to be a callable callback function; a non-function (including undefined) was supplied. This mirrors the spec TypeError for non-function iterables' callbacks.
Solutions
- Pass a function: mySet.forEach(v => console.log(v)).
- Default optional callbacks: cb = cb || (() => {}).
- Validate typeof callback === 'function' before calling forEach.
Example fix
// before
mySet.forEach(callbackName);
// after
if (typeof callbackName === 'function') { mySet.forEach(callbackName); } Defensive patterns
Strategy: validation
Validate before calling
if (typeof cb !== 'function') cb = () => {}; Type guard
function isFn(v) { return typeof v === 'function'; } Try / catch
try { mySet.forEach(cb); } catch (e) { if (String(e).includes('callback is not a function')) mySet.forEach(v => process(v)); else throw e; } Prevention
- Always pass an explicit function to forEach.
- Default optional callbacks to a no-op function, not undefined.
- Check for misspelled callback identifiers.
When it happens
Trigger: mySet.forEach() with no args; mySet.forEach('notAFunction'); passing a value that is null/undefined because a callback variable was never initialized.
Common situations: Typos where the intended callback name is misspelled or out of scope; optional callbacks defaulted to undefined instead of a no-op; refactors that dropped the arrow function.
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
- callback is not a function
- Constructor Set requires 'new'
- filter() needs two arguments: list and function
- forEach() needs two arguments: collection and function
- groupBy callback is not a function
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/12ddf34dfb096303.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsSetPrototype.java:98
}
private Object has(Context context, Object[] args) {
return asSet(context).has(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
private Object delete(Context context, Object[] args) {
return asSet(context).deleteValue(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
private Object clear(Context context, Object[] args) {
asSet(context).clearAll();
return Terms.UNDEFINED;
}
private Object forEach(Context context, Object[] args) {
JsSet s = asSet(context);
if (args.length == 0 || !(args[0] instanceof JsCallable cb)) {
throw JsErrorException.typeError("Set.prototype.forEach: callback is not a function");
}
Object thisArg = args.length > 1 ? args[1] : Terms.UNDEFINED;
CoreContext cc = context instanceof CoreContext c ? c : null;
Object savedThis = cc != null ? cc.thisObject : null;
try {
// Spec: forEach walks the live entry list. Entries added after the cursor
// (at the end) are visited; entries deleted before the cursor reaches them
// are skipped. Re-fetch the keyset on each step so additions show up.
int cursor = 0;
while (cursor < s.elements.size()) {
Iterator<Object> it = s.elements.keySet().iterator();
for (int i = 0; i < cursor && it.hasNext(); i++) it.next();
if (!it.hasNext()) break;
Object v = it.next();
if (cc != null) cc.thisObject = thisArg;
// Per spec: callback receives (value, value, set) — both first args identical
// (sets have no separate key vs value).
cb.call(context, new Object[]{v, v, s});View on GitHub (pinned to a22eb90246)