karatelabs/karate · error · JsErrorException
iterator.throw is not a function
Error message
iterator.throw is not a function
What it means
When a throw completion is delegated to an inner iterator and its 'throw' property is present but not callable (e.g. null, a number, an object), the engine throws 'iterator.throw is not a function'. Per GetMethod semantics this throws immediately without closing the iterator.
Solutions
- Ensure 'throw' is a function on the iterator object, or remove the property entirely so the missing-method path applies
- Convert the iterator to a generator to inherit correct throw semantics
- Check for accidental overwrites of iterator methods when extending the object
Example fix
// before
const it = { next() {...}, throw: null };
// after
const it = { next() {...}, throw(e) { return { done: true }; } }; Defensive patterns
Strategy: validation
Validate before calling
if ('throw' in it && typeof it.throw !== 'function') delete it.throw; // or fix to a function Type guard
function isCallableProp(obj, name) { return obj == null || !(name in obj) || typeof obj[name] === 'function'; } Try / catch
try { gen.throw(e); } catch (err) { if (String(err).includes('iterator.throw is not a function')) { /* repair iterator then rethrow */ } } Prevention
- Never use placeholder non-function values for method names
- Avoid data fields named next/return/throw on iterator objects
- Use generators to eliminate manual protocol maintenance
When it happens
Trigger: A custom iterator object has a non-function 'throw' property (typo, wrong assignment, or a placeholder value) and the consumer calls generator.throw() while suspended in yield* over that iterator.
Common situations: Assigning throw: true or throw: null as a placeholder; property-name collisions overwriting the method; partial iterator implementations copied from examples.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- iterator result is not an object
- The iterator does not provide a 'throw' method
- Generator is already running
- Result of the Symbol.iterator method is not an object
- iterator. is not a function
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/a730357fe6b02fbb.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/Interpreter.java:2981
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()) {
return Terms.UNDEFINED;
}
if (returned == null) {
// no return method: propagate the return completion
context.stopAndReturn(sent);
return Terms.UNDEFINED;View on GitHub (pinned to a22eb90246)