karatelabs/karate · error · io.karatelabs.js.EngineInterruptedException

<interrupted>

Error message

<interrupted>

What it means

JsGenerator.drive throws EngineInterruptedException (message "<interrupted>") when a generator resumes while the engine has been host-cancelled (HOST_CANCELLED outcome). The library converts a cooperative cancellation signal into this engine exception so generator frames unwind cleanly instead of running to completion.

Solutions

  1. Treat it as cancellation, not a bug: catch EngineInterruptedException and unwind without retrying.
  2. Check why the host cancelled (step timeout, abort call) and raise the timeout or shorten the generator work.
  3. Ensure blocking work inside generators is cancellable/segmented so cancellation lands promptly.
  4. If cancellation is unintended, audit host code paths that call engine stop/cancel APIs.

Example fix

// before
var v = gen.next(); // may throw <interrupted> on host cancel
// after
try { var v = gen.next(); } catch (e) { if (isInterrupted(e)) return; throw e; }
Defensive patterns

Strategy: try-catch

Validate before calling

if (engine.isCancelled()) return; // check before resuming the generator

Type guard

boolean isCancellation(Throwable t) { return t instanceof EngineInterruptedException || (t.getCause() instanceof EngineInterruptedException); }

Try / catch

try { return gen.next(); } catch (EngineInterruptedException e) { cleanup(); return null; }

Prevention

When it happens

Trigger: The host (e.g. Karate runtime, timeout watchdog, or user abort) cancels the engine context while a generator is mid-yield; next(), return(), or throw() on the generator then sees HOST_CANCELLED.

Common situations: Scenario/step timeouts in Karate cancelling long-running JS generators; test shutdown while an async generator is suspended; explicit engine cancellation API invoked from Java host code.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsGenerator.java:93

                throw JsErrorException.typeError("Generator is already running");
            }
            activation.retire(); // NOT_STARTED: no body code runs
            ctx.stopAndThrow(value);
            return Terms.UNDEFINED;
        }
        return drive(ctx, ResumeKind.THROW, value);
    }

    private Object drive(CoreContext ctx, ResumeKind kind, Object value) {
        StepOutcome outcome = activation.step(kind, value);
        return switch (outcome.kind) {
            case YIELDED -> result(outcome.value, false);
            case RETURNED -> result(outcome.value, true);
            case THREW -> {
                ctx.stopAndThrow(outcome.value);
                yield Terms.UNDEFINED;
            }
            case HOST_CANCELLED -> throw new EngineInterruptedException();
        };
    }

}

View on GitHub (pinned to a22eb90246)