karatelabs/karate · error · JsErrorException
Promise requires an engine
Error message
Promise requires an engine
What it means
The Promise constructor needs access to a karate-js Engine (for the microtask queue/AsyncScope). engineOf resolves the engine from the current Context, then Engine.current(); if both are absent, constructing or calling Promise throws 'Promise requires an engine'.
Solutions
- Ensure the Context used to evaluate Promise code has an Engine attached (context.getEngine() != null)
- Run the evaluation on the engine's thread, or set Engine.current(engine) for the duration of the call in custom threads
- Create/enter the engine before constructing Promises rather than reusing bare constructors cross-thread
- Route async JS through the engine's evaluation API instead of calling Promise internals directly
Example fix
// before
Context ctx = Context.newDetached(); // no engine
ctx.eval("new Promise(r => r(1))"); // TypeError: Promise requires an engine
// after
Engine engine = Engine.newEngine();
Context ctx = Context.newBuilder().engine(engine).build(); // engine bound
ctx.eval("new Promise(r => r(1))"); Defensive patterns
Strategy: try-catch
Validate before calling
if (context == null || context.getEngine() == null) throw new IllegalStateException('Promise code needs an Engine-bound Context or Engine.current()'); Type guard
function hasEngine(ctx) { return ctx != null && ctx.getEngine() != null; } Try / catch
try { return evalWithPromises(ctx, script); } catch (JsErrorException e) { if (String(e.getMessage()).contains('Promise requires an engine')) { Engine.current(engine); return evalWithPromises(ctx, script); } throw e; } Prevention
- Always create Promises through an engine-bound Context
- Set Engine.current(engine) on custom/worker threads before evaluating async JS
- In embedded hosts, keep all JS evaluation on threads where the engine is registered
When it happens
Trigger: Evaluating JS that touches Promise outside a managed engine context — e.g. calling the Promise constructor/resolve/reject functions from a detached Context with no engine attached and no thread-local Engine.current() set.
Common situations: Embedding the JS engine in a host application and invoking Promise-related functions from a non-engine thread; constructing Context objects manually without binding an Engine; async/await code evaluated in a headless/embedded harness.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- Promise requires an active evaluation
- engine is poisoned:
- unhandled promise rejection:
- unhandled promise rejection
- await on a promise that can never settle
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/241d019a51683e30.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsPromiseConstructor.java:63
JsPromiseConstructor() {
this.name = "Promise";
this.length = 1;
defineOwn("prototype", JsPromisePrototype.INSTANCE, PropertySlot.INTRINSIC);
defineOwn("resolve", new JsBuiltinMethod("resolve", 1, resolveDelegate), METHOD_ATTRS);
defineOwn("reject", new JsBuiltinMethod("reject", 1, (JsCallable) this::rejectStatic), METHOD_ATTRS);
defineOwn("all", new JsBuiltinMethod("all", 1, (JsCallable) this::all), METHOD_ATTRS);
defineOwn("allSettled", new JsBuiltinMethod("allSettled", 1, (JsCallable) this::allSettled), METHOD_ATTRS);
defineOwn("race", new JsBuiltinMethod("race", 1, (JsCallable) this::race), METHOD_ATTRS);
defineOwn("any", new JsBuiltinMethod("any", 1, (JsCallable) this::any), METHOD_ATTRS);
}
private static Engine engineOf(Context context) {
Engine engine = context == null ? null : context.getEngine();
if (engine == null) {
engine = Engine.current();
}
if (engine == null) {
throw JsErrorException.typeError("Promise requires an engine");
}
return engine;
}
private static AsyncScope scopeOf(Engine engine) {
AsyncScope scope = engine.currentScope();
if (scope == null) {
throw JsErrorException.typeError("Promise requires an active evaluation");
}
return scope;
}
static JsPromise newPromise(Context context) {
Engine engine = engineOf(context);
AsyncActivation.anyAsync = true;
return new JsPromise(engine, scopeOf(engine));
}
View on GitHub (pinned to a22eb90246)