karatelabs/karate · error · JsErrorException
Generator is already running
Error message
Generator is already running
What it means
The generator machinery (GeneratorActivation.step) throws this TypeError when a generator whose state is already RUNNING is asked to take another step. This corresponds to the ECMAScript rule that you cannot call next()/return()/throw() on a generator from inside its own execution (e.g. via its iterator indirectly). The state check is an AtomicReference compare so concurrent host callers also funnel here (line 151 is the direct state==RUNNING check).
Solutions
- Do not consume the generator from within its own execution — collect results first, then iterate
- If re-entrancy is needed, create a second independent generator instance
- Buffer yielded values into an array/queue and iterate the buffer inside the generator body
- In host code, synchronize or confine each generator to a single thread
Example fix
// before
function* g() { for (const v of g()) yield v; } // self-consumption
// after
function* g(src) { for (const v of src) yield v * 2; }
const it = g([1,2,3]); Defensive patterns
Strategy: try-catch
Validate before calling
// ensure you never iterate a generator inside its own body: // pass the source collection in as a parameter instead of self-referencing
Type guard
function canStep(gen) { return gen && !gen.__running; } Try / catch
try { var r = gen.next(); } catch (e) { if (String(e).includes('Generator is already running')) { /* restructure: don't re-enter */ } else { throw e; } } Prevention
- Never consume an iterator from inside its own generator body
- Buffer results before re-iterating
- One consumer per generator instance
When it happens
Trigger: Calling gen.next() (directly or through spread/for-of) from within the generator's own body or from a callback invoked while the generator is executing; re-entrant resume through shared state; two host threads stepping the same generator activation.
Common situations: Generator yields into a callback that itself consumes the same iterator; recursive iteration over a generator that feeds itself; multithreaded host code sharing a generator instance across threads.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 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
- Method Generator.prototype called on incompatible receiver
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/db23244a47572b91.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/GeneratorActivation.java:151
}
/** {@code return(v)} / {@code throw(e)} on a NOT_STARTED or DONE generator
* runs no body code — just retire it. */
void retire() {
state.set(State.DONE);
}
/**
* One driver step: deposit the resume input, hand the coroutine the lock,
* park until it yields / returns / throws, and return the outcome. Caller
* (JsGenerator) has already done brand/state shortcuts; this method owns
* the RUNNING transition.
*/
StepOutcome step(ResumeKind kind, Object value) {
anyGenerators = true;
State s = state.get();
if (s == State.RUNNING) {
throw JsErrorException.typeError("Generator is already running");
}
if (s == State.DONE) {
// raced with a concurrent completion — treat as done
return new StepOutcome(OutcomeKind.RETURNED, Terms.UNDEFINED);
}
if (!state.compareAndSet(s, State.RUNNING)) {
// a concurrent host caller won the step; spec answer is the same
// "already running" TypeError
throw JsErrorException.typeError("Generator is already running");
}
AtomicReference<StepOutcome> cell = new AtomicReference<>();
stepCell = cell;
resumeKind = kind;
resumeValue = value;
driver = Thread.currentThread();
// register-only-if-open: a RUNNING step is scope-owned, cancellable
// work; a closed scope must not accept it
AsyncScope scope = engine.currentScope();View on GitHub (pinned to a22eb90246)