karatelabs/karate · error · JsErrorException
Method Generator.prototype called on incompatible receiver
Error message
Method Generator.prototype called on incompatible receiver
What it means
A method from Generator.prototype (next, return, or throw) was invoked with a `this` that is not a JsGenerator. asGenerator narrows the receiver and throws a TypeError when the check fails, matching the spec's 'incompatible receiver' behavior for builtin prototype methods.
Solutions
- Call the methods directly on the generator object: gen.next(), not a detached reference.
- Bind detached methods: `const next = gen.next.bind(gen)`.
- Guard with a check that the value is a generator before delegating.
- Fix adapters/proxies so they forward method calls with the generator as receiver.
Example fix
// before var next = gen.next; next(); // this is undefined // after var next = gen.next.bind(gen); next();
Defensive patterns
Strategy: type-guard
Validate before calling
if (!gen || typeof gen.next !== 'function') { throw new Error('not a generator: ' + gen); } Type guard
function isGenerator(v) { return v != null && typeof v.next === 'function' && typeof v[Symbol && Symbol.toStringTag || 'next'] !== 'undefined' && Object.prototype.toString.call(v) === '[object Generator]'; } Try / catch
try { gen.next(v); } catch (e) { if (String(e).indexOf('incompatible receiver') !== -1) { karate.log('lost generator receiver'); } else { throw e; } } Prevention
- Do not detach generator methods without binding: use gen.next.bind(gen)
- Forward calls with the generator as receiver in adapters/proxies
- Validate the value is a generator before handing it to iteration helpers
When it happens
Trigger: Calling gen.next()/gen.return()/gen.throw() after the receiver was reassigned to a non-generator; detaching the method (e.g. `var n = gen.next; n()`) so `this` is undefined; passing a plain object that mimics a generator into code that calls its .next.
Common situations: Storing the next method as a callback without binding; wrapping generators in proxies/adapters that lose the receiver; iterating with a helper typed loosely that receives a non-generator value.
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
- Generator is already running
- iterator result is not an object
- The iterator does not provide a 'throw' method
- iterator.throw is not a function
- Generator is already running
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/c0fd1f8790053cf0.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsGeneratorPrototype.java:50
class JsGeneratorPrototype extends Prototype {
static final JsGeneratorPrototype INSTANCE = new JsGeneratorPrototype();
private JsGeneratorPrototype() {
super(JsObjectPrototype.INSTANCE);
install("next", 1, this::next);
install("return", 1, this::returnMethod);
install("throw", 1, this::throwMethod);
// a generator is its own iterator
install(IterUtils.SYMBOL_ITERATOR, 0, (context, args) -> asGenerator(context));
}
private static JsGenerator asGenerator(Context context) {
Object thisObj = context.getThisObject();
if (thisObj instanceof JsGenerator g) {
return g;
}
throw JsErrorException.typeError("Method Generator.prototype called on incompatible receiver");
}
private static Object arg(Object[] args) {
return args.length > 0 ? args[0] : Terms.UNDEFINED;
}
private Object next(Context context, Object[] args) {
return asGenerator(context).next((CoreContext) context, arg(args));
}
private Object returnMethod(Context context, Object[] args) {
return asGenerator(context).returnValue((CoreContext) context, arg(args));
}
private Object throwMethod(Context context, Object[] args) {
return asGenerator(context).throwValue((CoreContext) context, arg(args));
}
View on GitHub (pinned to a22eb90246)