karatelabs/karate · error · JsErrorException

iterator 'return' result is not an object

Error message

iterator 'return' result is not an object

What it means

When IteratorClose runs outside an error path (dueToError == false), the spec requires the result of calling the iterator's `return()` to be an object. If return() returns a primitive, null, or undefined, karate throws this TypeError. If an error was already in flight, return()'s bad result is tolerated and the original completion/error takes precedence.

Solutions

  1. Return an object from return(): `return: function() { cleanup(); return { done: true }; }`.
  2. Omit `return` entirely if there is nothing meaningful to do — a missing return method is legal.
  3. Wrap void cleanups: `return: function() { cleanup(); return {}; }`.

Example fix

// before
return: function() { file.close(); }
// after
return: function() { file.close(); return { done: true }; }
Defensive patterns

Strategy: validation

Validate before calling

var r = it.return();
if (r == null || typeof r !== 'object') throw new TypeError("return() must return an object");

Type guard

function returnsObject(fn) { var r = fn(); return r != null && typeof r === 'object'; }

Try / catch

try { for (var x of it) { if (stop) break; } } catch (e) { if (String(e).indexOf("'return' result is not an object") !== -1) { /* resource already cleaned up; log */ } else { throw e; } }

Prevention

When it happens

Trigger: Breaking out of a for-of loop whose iterator's `return()` method returns nothing (implicit undefined) or a primitive, e.g. `return: function() { close(); }` with no return statement.

Common situations: Custom iterators with cleanup hooks that forget to return `{done:true}` from return(); resources (files, connections) wrapped as iterators whose return() just calls a void cleanup function.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/181878a6b786e41a. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/IterUtils.java:475

                    }
                    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)) {
                        throw JsErrorException.typeError("iterator 'return' result is not an object");
                    }
                } finally {
                    if (hadError) {
                        ((CoreContext) ctx).stopAndThrow(savedError); // original completion wins
                    }
                }
            }
        };
    }

    private static void clearError(Context ctx) {
        if (ctx instanceof CoreContext cc && cc.isError()) {
            cc.reset();
        }
    }

    private static final Object[] EMPTY_ARGS = new Object[0];

View on GitHub (pinned to a22eb90246)