karatelabs/karate · error · JsErrorException
iterator result is not an object
Error message
iterator result is not an object
What it means
After calling `next()` on a user-supplied iterator object, karate requires the returned step to be an object (per spec IteratorStep, which does ToObject on the result). If next() returns a primitive, null, or undefined, this TypeError is thrown.
Solutions
- Always return a result object from next(): `return { value: v, done: false }`.
- Wrap primitive returns: `return { value: compute(), done: false };`.
- Ensure the terminal call also returns an object: `return { done: true };`.
Example fix
// before
next: function() { return items[i++]; }
// after
next: function() { return i < items.length ? { value: items[i++], done: false } : { done: true }; } Defensive patterns
Strategy: type-guard
Validate before calling
var step = it.next();
if (step == null || typeof step !== 'object') throw new TypeError('next() must return an object'); Type guard
function isIteratorStep(s) { return s != null && typeof s === 'object' && typeof s.done === 'boolean'; } Try / catch
try { var step = it.next(); consume(step.value); } catch (e) { if (String(e).indexOf('not an object') !== -1) { /* treat iterator as broken */ } else { throw e; } } Prevention
- next() must always return {value, done} objects, including at exhaustion
- Avoid returning raw values from helper functions delegated to by next()
- Test the full pull cycle with Array.from
When it happens
Trigger: A custom iterator's next() function returns a bare value like `return i++` or `return null` instead of `{value: x, done: bool}`, and the iterator is consumed by for-of, spread, or Array.from.
Common situations: Beginner iterator implementations returning values directly, refactored next() that dropped the result-object wrapper, or next() delegating to a function that returns a primitive.
Related errors
- Result of iterator method is not an object
- iterator.next is not a function
- Result of the Symbol.iterator method 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/52756a46cb0767c3.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/IterUtils.java:220
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);
} finally {
cc.thisObject = savedThis;
}
} else {
step = nextCallable.call(context, EMPTY_ARGS);
}
if (isJsErrored(context)) { done = true; return; }
if (!(step instanceof ObjectLike stepObj)) {
throw JsErrorException.typeError("iterator result is not an object");
}
if (Terms.isTruthy(readMember(stepObj, "done", context))) {
done = true;
return;
}
if (isJsErrored(context)) { done = true; return; }
pending = readMember(stepObj, "value", context);
if (pending == null && !hasProperty(stepObj, "value")) {
// A step result with no `value` member reads as undefined
// (spec GetV) — the distinction matters downstream, where
// a destructuring default fires on undefined but not null.
pending = Terms.UNDEFINED;
}
if (isJsErrored(context)) { done = true; return; }
fetched = true;
}
@OverrideView on GitHub (pinned to a22eb90246)