{"record":{"id":"488c0d190a1e0561","repo":"karatelabs/karate","slug":"map-prototype-foreach-callback-is-not-a-function","errorCode":null,"errorMessage":"Map.prototype.forEach: callback is not a function","messagePattern":"Map\\.prototype\\.forEach: callback is not a function","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsMapPrototype.java","lineNumber":99,"sourceCode":"    }\n\n    private Object has(Context context, Object[] args) {\n        return asMap(context).hasKey(args.length > 0 ? args[0] : Terms.UNDEFINED);\n    }\n\n    private Object delete(Context context, Object[] args) {\n        return asMap(context).deleteKey(args.length > 0 ? args[0] : Terms.UNDEFINED);\n    }\n\n    private Object clear(Context context, Object[] args) {\n        asMap(context).clearAll();\n        return Terms.UNDEFINED;\n    }\n\n    private Object forEach(Context context, Object[] args) {\n        JsMap m = asMap(context);\n        if (args.length == 0 || !(args[0] instanceof JsCallable cb)) {\n            throw JsErrorException.typeError(\"Map.prototype.forEach: callback is not a function\");\n        }\n        // Spec: forEach walks the live entry list. Entries appended during iteration\n        // are visited; deletions ahead of the cursor are skipped naturally because the\n        // cursor advances past them.\n        int cursor = 0;\n        while (cursor < m.entries.size()) {\n            Iterator<Map.Entry<Object, Object>> it = m.entries.entrySet().iterator();\n            for (int i = 0; i < cursor && it.hasNext(); i++) it.next();\n            if (!it.hasNext()) break;\n            Map.Entry<Object, Object> e = it.next();\n            cb.call(context, new Object[]{e.getValue(), e.getKey(), m});\n            cursor++;\n        }\n        return Terms.UNDEFINED;\n    }\n\n    private Object keys(Context context, Object[] args) {\n        JsMap m = asMap(context);","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsMapPrototype.java#L81-L117","documentation":"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.","triggerScenarios":"`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)`).","commonSituations":"Typos in callback names; leaving placeholder args during refactor; passing config values (like a callback name string from JSON) instead of actual functions.","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"],"exampleFix":"// before\nmap.forEach('logEach'); // TypeError: callback is not a function\n// after\nmap.forEach((v, k) => karate.log(k, v));","handlingStrategy":"type-guard","validationCode":"if (typeof cb !== 'function') { throw new Error('forEach needs a function callback'); }","typeGuard":"function isFn(x) { return typeof x === 'function'; }","tryCatchPattern":"try {\n  m.forEach(cb);\n} catch (e) {\n  if (String(e.message).includes('callback is not a function')) {\n    m.forEach(() => {}); // or surface a clear config error\n  } else throw e;\n}","preventionTips":["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"],"tags":["javascript","map","callback","typeerror"],"backgroundTag":"missing-required-argument","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}