karatelabs/karate · error · JsErrorException

The iterator does not provide a 'throw' method

Error message

The iterator does not provide a 'throw' method

What it means

When a throw completion is sent into a delegated iterator (yield* with .throw()), and the iterator object has no 'throw' method at all, the engine reports that the iterator does not provide a 'throw' method. This is the ECMAScript-specified message for the yield* delegation path; it follows IteratorClose of the inner iterator first.

Solutions

  1. Add a throw method to the custom iterator object
  2. Replace the hand-rolled iterator with a generator function, which provides next/return/throw automatically
  3. Avoid calling .throw() on the outer generator while it is delegated into a plain iterator

Example fix

// before
const it = { next() { ... } }; // no throw
// after
function* gen() { ... } // generator supplies throw/return
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof innerIterator.throw !== 'function') { /* avoid delegating throw into this iterator */ }

Type guard

function supportsThrow(it) { return it != null && typeof it.throw === 'function'; }

Try / catch

try { gen.throw(e); } catch (err) { if (String(err).includes("does not provide a 'throw'")) { gen.return(undefined); /* close cleanly instead */ } }

Prevention

When it happens

Trigger: Calling generator.throw(err) on a generator that is currently suspended inside a yield* delegating to a custom iterator lacking a throw method, or for-of/iterator code paths that forward throw completions to a plain iterator object.

Common situations: Hand-rolled iterator objects (only next(), maybe return()) delegated to via yield*; consumers expecting full generator protocol from plain iterators; mixing generator throw with arrays wrapped through the generic iterator adapter.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/Interpreter.java:2975

                        return Terms.UNDEFINED;
                    }
                }
                case THROW -> {
                    Object throwFn = iterObj.getMember("throw", iterObj, context);
                    if (context.isStopped()) {
                        return Terms.UNDEFINED; // a throwing `throw` getter wins outright
                    }
                    if (throwFn == null || throwFn == Terms.UNDEFINED) {
                        // ABSENT throw: close the delegate (validating
                        // return()'s result when present), then TypeError
                        Object closed = invokeIteratorMethod(iterObj, "return", null, context, false);
                        if (context.isStopped()) {
                            return Terms.UNDEFINED;
                        }
                        if (closed != null && !(closed instanceof ObjectLike)) {
                            throw JsErrorException.typeError("iterator result is not an object");
                        }
                        throw JsErrorException.typeError(
                                "The iterator does not provide a 'throw' method");
                    }
                    if (!(throwFn instanceof JsCallable throwCallable)) {
                        // GetMethod: a PRESENT non-callable throws immediately,
                        // with no iterator close
                        throw JsErrorException.typeError("iterator.throw is not a function");
                    }
                    step = invokeIteratorCallable(iterObj, throwCallable, sent, context);
                    if (context.isStopped()) {
                        return Terms.UNDEFINED;
                    }
                    if (!(step instanceof ObjectLike)) {
                        throw JsErrorException.typeError("iterator result is not an object");
                    }
                }
                case RETURN -> {
                    Object returned = invokeIteratorMethod(iterObj, "return", sent, context, false);
                    if (context.isStopped()) {

View on GitHub (pinned to a22eb90246)