{"record":{"id":"1b67ba110890f9d7","repo":"karatelabs/karate","slug":"result-of-the-symbol-iterator-method-is-not-an-object-1b67ba","errorCode":null,"errorMessage":"Result of the Symbol.iterator method is not an object","messagePattern":"Result of the Symbol\\.iterator method is not an object","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/IterUtils.java","lineNumber":358,"sourceCode":"            Object savedThis = cc.thisObject;\n            cc.thisObject = receiver;\n            try {\n                iter = iteratorFn.call(cc, EMPTY_ARGS);\n            } finally {\n                cc.thisObject = savedThis;\n            }\n        } else {\n            iter = iteratorFn.call(context, EMPTY_ARGS);\n        }\n        // A `throw` inside the @@iterator method sets the cooperative stop-flag\n        // rather than raising a Java exception. The pending error must win —\n        // an exhausted iterator lets the caller unwind without overwriting it\n        // with the not-an-object TypeError below.\n        if (isJsErrored(context)) {\n            return exhaustedIterator();\n        }\n        if (!(iter instanceof ObjectLike iterObj)) {\n            throw JsErrorException.typeError(\"Result of the Symbol.iterator method is not an object\");\n        }\n        return new JsIterator() {\n            Object pending;\n            boolean fetched;\n            boolean done;\n\n            private void fetch() {\n                if (fetched || done) return;\n                Object nextFn = iterObj.getMember(\"next\");\n                if (!(nextFn instanceof JsCallable nextCallable)) {\n                    throw JsErrorException.typeError(\"iterator.next is not a function\");\n                }\n                Object step;\n                if (context instanceof CoreContext cc) {\n                    Object savedThis = cc.thisObject;\n                    cc.thisObject = iterObj;\n                    try {\n                        step = nextCallable.call(cc, EMPTY_ARGS);","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/IterUtils.java#L340-L376","documentation":"In userIterator (the tryGetIterator path for objects with a Symbol.iterator method), karate calls the method and requires the result to be an object per the spec. If Symbol.iterator returns null/undefined or a primitive instead of an iterator object, this TypeError is thrown.","triggerScenarios":"An object defines Symbol.iterator but the method returns null, undefined, a number, or a string — e.g. `obj[Symbol.iterator] = function() { return this.items; }` where items is an array-returning getter misused, or the method forgets to return the iterator.","commonSituations":"Custom collection classes in Karate JS with a partially implemented iterator protocol, or Symbol.iterator copied from a class where it returns a value rather than an iterator (mixing it up with valueOf-style contracts).","solutions":["Have Symbol.iterator return an object with a callable `next` (e.g. an index-closure iterator).","Return `this` if the object itself already has a `next` method.","Use a generator function (`function*`) as the source when available so the engine builds a valid iterator."],"exampleFix":"// before\nobj[Symbol.iterator] = function() { return this.items; };\n// after\nobj[Symbol.iterator] = function() {\n  var items = this.items, i = 0;\n  return { next: function() { return i < items.length ? { value: items[i++], done: false } : { done: true }; } };\n};","handlingStrategy":"type-guard","validationCode":"var r = obj[Symbol.iterator] && obj[Symbol.iterator]();\nif (r == null || typeof r !== 'object' || typeof r.next !== 'function') throw new TypeError('bad Symbol.iterator result');","typeGuard":"function implementsIterable(o) { return o != null && typeof o[Symbol.iterator] === 'function' && typeof o[Symbol.iterator]().next === 'function'; }","tryCatchPattern":"try { for (var x of obj) { ... } } catch (e) { if (String(e).indexOf('Symbol.iterator method is not an object') !== -1) { /* fall back to manual iteration */ } else { throw e; } }","preventionTips":["Symbol.iterator must return an iterator object, not a value or the underlying collection","Prefer generators over hand-written iterators where supported","Sanity-check with Array.from(obj) in tests"],"tags":["javascript","iterator-protocol","typeerror"],"backgroundTag":"unexpected-response-shape","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"}