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

  1. Call the methods directly on the generator object: gen.next(), not a detached reference.
  2. Bind detached methods: `const next = gen.next.bind(gen)`.
  3. Guard with a check that the value is a generator before delegating.
  4. 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

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


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)