{"record":{"id":"a433f272bf5357ab","repo":"karatelabs/karate","slug":"iterator-return-is-not-a-function","errorCode":null,"errorMessage":"iterator 'return' is not a function","messagePattern":"iterator 'return' is not a function","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/IterUtils.java","lineNumber":456,"sourceCode":"                // the original completion is a throw it wins, so on dueToError the\n                // parked error is restored and anything return() raises is discarded.\n                boolean hadError = isJsErrored(ctx);\n                Object savedError = hadError ? ((CoreContext) ctx).getErrorThrown() : null;\n                if (hadError) {\n                    ((CoreContext) ctx).reset();\n                }\n                try {\n                    Object retFn = readMember(iterObj, \"return\", ctx);\n                    if (isJsErrored(ctx)) {\n                        if (dueToError) clearError(ctx); // throwing return getter, discard\n                        return;\n                    }\n                    if (retFn == null || retFn == Terms.UNDEFINED) {\n                        return; // no return method — nothing to close\n                    }\n                    if (!(retFn instanceof JsCallable retCallable)) {\n                        if (dueToError) return;\n                        throw JsErrorException.typeError(\"iterator 'return' is not a function\");\n                    }\n                    Object result;\n                    if (ctx instanceof CoreContext cc) {\n                        Object savedThis = cc.thisObject;\n                        cc.thisObject = iterObj;\n                        try {\n                            result = retCallable.call(cc, EMPTY_ARGS);\n                        } finally {\n                            cc.thisObject = savedThis;\n                        }\n                    } else {\n                        result = retCallable.call(ctx, EMPTY_ARGS);\n                    }\n                    if (isJsErrored(ctx)) {\n                        if (dueToError) clearError(ctx); // return() threw, discard\n                        return;                           // else propagate return()'s throw\n                    }\n                    if (!dueToError && !(result instanceof ObjectLike)) {","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/IterUtils.java#L438-L474","documentation":"IterUtils.close implements IteratorClose: when a for-of loop exits early (break, throw, return), it calls the iterator's `return` method. Per the spec, if `return` exists it must be callable; if it is a non-callable non-null value and the loop is NOT already unwinding due to an error, karate throws this TypeError (when dueToError is true the bad `return` is ignored so the original error wins).","triggerScenarios":"Breaking out of (or throwing inside) a for-of over a custom iterator whose object has a `return` property set to a non-function value (e.g. `return: true` as a flag name collision, or `return` assigned to a non-callable).","commonSituations":"Naming a data member `return` on an iterator object (reserved-word misuse), or implementing return() as a property holding a value instead of a method.","solutions":["Make `return` a function: `return: function() { cleanup(); return {done:true}; }`.","Remove the invalid `return` member if cleanup is unnecessary — absence is allowed.","Rename any data property that collides with the protocol method name."],"exampleFix":"// before\nvar it = { next: next, return: false };\n// after\nvar it = { next: next, return: function() { cleanup(); return { done: true }; } };","handlingStrategy":"type-guard","validationCode":"if (it.return !== undefined && typeof it.return !== 'function') throw new TypeError(\"iterator 'return' must be a function\");","typeGuard":"function hasValidReturnMethod(o) { return o.return === undefined || typeof o.return === 'function'; }","tryCatchPattern":"try { for (var x of it) { if (x > 10) break; } } catch (e) { if (String(e).indexOf(\"'return' is not a function\") !== -1) { /* cleanup manually */ } else { throw e; } }","preventionTips":["Never store data under the key 'return' on iterator objects","Implement return() as a real function returning {done:true}","Delete the return member if no early-exit cleanup is needed"],"tags":["javascript","iterator-protocol","cleanup","typeerror"],"backgroundTag":"invalid-argument-value","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"}