karatelabs/karate · error · JsErrorException
Result of the Symbol.iterator method is not an object
Error message
Result of the Symbol.iterator method is not an object
What it means
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.
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.
Example fix
// before
obj[Symbol.iterator] = function() { return this.items; };
// after
obj[Symbol.iterator] = function() {
var items = this.items, i = 0;
return { next: function() { return i < items.length ? { value: items[i++], done: false } : { done: true }; } };
}; Defensive patterns
Strategy: type-guard
Validate before calling
var r = obj[Symbol.iterator] && obj[Symbol.iterator]();
if (r == null || typeof r !== 'object' || typeof r.next !== 'function') throw new TypeError('bad Symbol.iterator result'); Type guard
function implementsIterable(o) { return o != null && typeof o[Symbol.iterator] === 'function' && typeof o[Symbol.iterator]().next === 'function'; } Try / catch
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; } } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Result of iterator method is not an object
- iterator.next is not a function
- iterator result is not an object
- iterator 'return' is not a function
- iterator 'return' result is not an object
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/1b67ba110890f9d7.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/IterUtils.java:358
Object savedThis = cc.thisObject;
cc.thisObject = receiver;
try {
iter = iteratorFn.call(cc, EMPTY_ARGS);
} finally {
cc.thisObject = savedThis;
}
} else {
iter = iteratorFn.call(context, EMPTY_ARGS);
}
// A `throw` inside the @@iterator method sets the cooperative stop-flag
// rather than raising a Java exception. The pending error must win —
// an exhausted iterator lets the caller unwind without overwriting it
// with the not-an-object TypeError below.
if (isJsErrored(context)) {
return exhaustedIterator();
}
if (!(iter instanceof ObjectLike iterObj)) {
throw JsErrorException.typeError("Result of the Symbol.iterator method is not an object");
}
return new JsIterator() {
Object pending;
boolean fetched;
boolean done;
private void fetch() {
if (fetched || done) return;
Object nextFn = iterObj.getMember("next");
if (!(nextFn instanceof JsCallable nextCallable)) {
throw JsErrorException.typeError("iterator.next is not a function");
}
Object step;
if (context instanceof CoreContext cc) {
Object savedThis = cc.thisObject;
cc.thisObject = iterObj;
try {
step = nextCallable.call(cc, EMPTY_ARGS);View on GitHub (pinned to a22eb90246)