karatelabs/karate · error · JsErrorException
iterator 'return' is not a function
Error message
iterator 'return' is not a function
What it means
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).
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.
Example fix
// before
var it = { next: next, return: false };
// after
var it = { next: next, return: function() { cleanup(); return { done: true }; } }; Defensive patterns
Strategy: type-guard
Validate before calling
if (it.return !== undefined && typeof it.return !== 'function') throw new TypeError("iterator 'return' must be a function"); Type guard
function hasValidReturnMethod(o) { return o.return === undefined || typeof o.return === 'function'; } Try / catch
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; } } Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- iterator 'return' result is not an object
- Result of iterator method is not an object
- iterator.next is not a function
- iterator result is not an object
- Result of the Symbol.iterator method is not an object
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/a433f272bf5357ab.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/IterUtils.java:456
// the original completion is a throw it wins, so on dueToError the
// parked error is restored and anything return() raises is discarded.
boolean hadError = isJsErrored(ctx);
Object savedError = hadError ? ((CoreContext) ctx).getErrorThrown() : null;
if (hadError) {
((CoreContext) ctx).reset();
}
try {
Object retFn = readMember(iterObj, "return", ctx);
if (isJsErrored(ctx)) {
if (dueToError) clearError(ctx); // throwing return getter, discard
return;
}
if (retFn == null || retFn == Terms.UNDEFINED) {
return; // no return method — nothing to close
}
if (!(retFn instanceof JsCallable retCallable)) {
if (dueToError) return;
throw JsErrorException.typeError("iterator 'return' is not a function");
}
Object result;
if (ctx instanceof CoreContext cc) {
Object savedThis = cc.thisObject;
cc.thisObject = iterObj;
try {
result = retCallable.call(cc, EMPTY_ARGS);
} finally {
cc.thisObject = savedThis;
}
} else {
result = retCallable.call(ctx, EMPTY_ARGS);
}
if (isJsErrored(ctx)) {
if (dueToError) clearError(ctx); // return() threw, discard
return; // else propagate return()'s throw
}
if (!dueToError && !(result instanceof ObjectLike)) {View on GitHub (pinned to a22eb90246)