{"record":{"id":"fa7d1cb4dfdbaa78","repo":"karatelabs/karate","slug":"promise-requires-an-active-evaluation","errorCode":null,"errorMessage":"Promise requires an active evaluation","messagePattern":"Promise requires an active evaluation","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsPromiseConstructor.java","lineNumber":71,"sourceCode":"        defineOwn(\"race\", new JsBuiltinMethod(\"race\", 1, (JsCallable) this::race), METHOD_ATTRS);\n        defineOwn(\"any\", new JsBuiltinMethod(\"any\", 1, (JsCallable) this::any), METHOD_ATTRS);\n    }\n\n    private static Engine engineOf(Context context) {\n        Engine engine = context == null ? null : context.getEngine();\n        if (engine == null) {\n            engine = Engine.current();\n        }\n        if (engine == null) {\n            throw JsErrorException.typeError(\"Promise requires an engine\");\n        }\n        return engine;\n    }\n\n    private static AsyncScope scopeOf(Engine engine) {\n        AsyncScope scope = engine.currentScope();\n        if (scope == null) {\n            throw JsErrorException.typeError(\"Promise requires an active evaluation\");\n        }\n        return scope;\n    }\n\n    static JsPromise newPromise(Context context) {\n        Engine engine = engineOf(context);\n        AsyncActivation.anyAsync = true;\n        return new JsPromise(engine, scopeOf(engine));\n    }\n\n    @Override\n    public Object call(Context context, Object[] args) {\n        CallInfo callInfo = context.getCallInfo();\n        if (callInfo == null || !callInfo.constructor) {\n            throw JsErrorException.typeError(\"Promise constructor cannot be invoked without 'new'\");\n        }\n        Object executor = AsyncSupport.arg(args, 0);\n        if (!(executor instanceof JsCallable callable)) {","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsPromiseConstructor.java#L53-L89","documentation":"Karate's JS engine exposes Promise via `scopeOf`, which fetches the engine's current AsyncScope. Promises only make sense while a script evaluation with an async scope is running (microtask queue attached). If `engine.currentScope()` returns null — e.g. Promise is touched outside any evaluation, from another thread, or after evaluation finished — the engine throws this TypeError instead of silently misbehaving.","triggerScenarios":"Calling `new Promise(...)` or `Promise.resolve()/reject()` when no AsyncScope is active: accessing the Promise global outside `eval()` on the engine, invoking the constructor from a non-script thread, or calling it after the evaluation has completed.","commonSituations":"Embedding karate-js in a host app and invoking JS callbacks on a plain Java thread without pushing a scope; using Promise inside a synchronous one-shot eval that tears down its scope before the constructor runs; racing two engine usages across threads.","solutions":["Ensure Promise usage happens inside a live script evaluation; don't cache or call Promise-related values after eval returns.","If embedding, run Promise-dependent code on the engine's evaluation thread (or via the engine's async execution entry points) rather than a custom thread.","Check that no code path nulls out or completes the engine's current scope before the constructor is invoked."],"exampleFix":"// before: host thread invokes JS directly\nexecutor.submit(() -> engine.eval(\"new Promise(r => r(1))\"));\n// after: run through the engine's own evaluation/async path\nengine.submit(\"new Promise(r => r(1))\"); // engine manages scope","handlingStrategy":"type-guard","validationCode":"// host-side (Java): only evaluate Promise code inside a live evaluation\nif (engine.currentScope() == null) {\n    throw new IllegalStateException(\"Promise used outside active evaluation\");\n}","typeGuard":"function hasActiveScope(engine) { return engine && typeof engine.currentScope === 'function' && engine.currentScope() != null; }","tryCatchPattern":"try { return evalUserScript(); } catch (e) { if (String(e).includes('Promise requires an active evaluation')) { /* re-run on evaluation thread */ } else { throw e; } }","preventionTips":["Never call Promise-dependent JS from host threads outside the engine's evaluation lifecycle.","Keep async JS entry points routed through the engine's own async APIs.","Document that cached function references into JS must be invoked while the evaluation is alive."],"tags":["javascript","promise","async","engine"],"backgroundTag":"no-active-evaluation","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}