karatelabs/karate · error · JsErrorException
Promise constructor cannot be invoked without 'new'
Error message
Promise constructor cannot be invoked without 'new'
What it means
Per the ES spec, Promise is a constructor and must be called with `new`. Karate checks the call's CallInfo flag `constructor`; a bare `Promise(...)` call reaches `call()` without constructor mode and throws this TypeError. This mirrors browsers/V8 exactly (`TypeError: Promise resolver X is not a constructor`-style rejection of missing new).
Solutions
- Add the `new` keyword: `new Promise((resolve, reject) => {...})`.
- If wrapping, bind through a helper that constructs: `const make = (ex) => new Promise(ex);`
- Search the script for direct `Promise(` call sites (no preceding new).
Example fix
// before const p = Promise((resolve) => resolve(1)); // after const p = new Promise((resolve) => resolve(1));
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof Promise !== 'function') throw new Error('Promise unavailable');
// always construct:
if (typeof executor !== 'function') throw new TypeError('executor must be a function'); Type guard
function isPromiseCtor(f) { return f === Promise; } Try / catch
try { const p = new Promise(executor); } catch (e) { if (e instanceof TypeError) { /* missing 'new' or bad executor */ } throw e; } Prevention
- Lint rule: flag bare `Promise(` calls without `new`.
- Never alias Promise for direct invocation; alias a factory instead.
- Code review Promise usage after refactors of async code.
When it happens
Trigger: Writing `Promise(...)` or `Promise.call(...)` instead of `new Promise(...)`; forwarding Promise as a plain function reference, e.g. `const P = Promise; P(executor)`.
Common situations: Refactored code where `new` was dropped; destructured/aliased Promise; code translated from languages where object construction doesn't use `new`.
Related errors
- <JS rejection reason>
- is not a constructor
- Class constructor cannot be invoked without 'new
- is not a constructor
- is not a constructor
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/f550413e61fb7749.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsPromiseConstructor.java:86
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));
}
@Override
public Object call(Context context, Object[] args) {
CallInfo callInfo = context.getCallInfo();
if (callInfo == null || !callInfo.constructor) {
throw JsErrorException.typeError("Promise constructor cannot be invoked without 'new'");
}
Object executor = AsyncSupport.arg(args, 0);
if (!(executor instanceof JsCallable callable)) {
throw JsErrorException.typeError("Promise resolver is not a function");
}
JsPromise promise = newPromise(context);
AtomicBoolean claimed = new AtomicBoolean();
JsCallable resolveFn = (ctx, a) -> {
if (claimed.compareAndSet(false, true)) {
AsyncSupport.settleFromCallback(promise, AsyncSupport.arg(a, 0), false);
}
return Terms.UNDEFINED;
};
JsCallable rejectFn = (ctx, a) -> {
if (claimed.compareAndSet(false, true)) {
AsyncSupport.settleFromCallback(promise, AsyncSupport.arg(a, 0), true);
}
return Terms.UNDEFINED;View on GitHub (pinned to a22eb90246)