karatelabs/karate · error · JsErrorException

is not a constructor

Error message

${operand.getTextIncludingWhitespace()} is not a constructor

What it means

Thrown when a `new X(...)` expression evaluates to a callable that is not constructable (or not a callable at all). Karate's JS engine tracks the [[Construct]] internal slot per callable; arrow functions, object-literal methods, and plain functions defined without construct semantics reject `new`. The error uses the original operand text so the offending expression appears in the message.

Solutions

  1. Use a regular `function` declaration or a class instead of an arrow function when calling with `new`.
  2. Verify with `typeof expr === 'function'` that the operand is a constructor-like callable before using `new`.
  3. Remove `new` if a plain call was intended (e.g. `Math.max(1,2)` needs no `new`).

Example fix

// before
var Point = (x, y) => ({x, y});
var p = new Point(1, 2);
// after
function Point(x, y) { this.x = x; this.y = y; }
var p = new Point(1, 2);
Defensive patterns

Strategy: type-guard

Validate before calling

// before `new`
if (typeof Expr !== 'function') throw new Error(Expr + ' is not constructable');

Type guard

function isConstructable(v) { return typeof v === 'function' && !/^\s*\(?[^)]*\)?\s*=>/.test(String(v)); }

Try / catch

try { var o = new Expr(); } catch (e) { /* TypeError: not a constructor — fall back */ o = Expr(); }

Prevention

When it happens

Trigger: Evaluating `new expr()` in Karate JS where expr evaluates to a non-constructable JsCallable — e.g. `new (() => {})()`, `new Math.max()`, or a JS function object defined without constructability.

Common situations: Porting Node scripts into Karate feature files that use `new` on arrow functions or built-ins; typos where the intended class name resolves to a helper function or bound method.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/Interpreter.java:773

    // template is itself a MemberExpression whose evaluation is the function
    // result, and `new` applies to that result with no arguments.
    private static Object evalNewExpr(Node node, CoreContext context) {
        // NEW_EXPR -> [NEW, EXPR -> [<operand>]]; evalFnCall expects the EXPR wrapper.
        Node exprWrap = node.get(1);
        Node operand = exprWrap.getFirst();
        if (operand.type != NodeType.FN_TAGGED_TEMPLATE_EXPR) {
            return evalFnCall(exprWrap, context, true);
        }
        // Per spec, `new tag`x`` applies new to the result of the tagged template
        // invocation, not to the tag itself. Evaluate the tagged template, then
        // construct the result with no args. (`new tag`x`()` parses as FN_CALL_EXPR
        // wrapping FN_TAGGED_TEMPLATE_EXPR and goes through the default path above.)
        Object callable = evalFnTaggedTemplate(operand, context);
        if (context.isError()) {
            return Terms.UNDEFINED;
        }
        if (!(callable instanceof JsCallable c) || !c.isConstructable()) {
            throw JsErrorException.typeError(operand.getTextIncludingWhitespace() + " is not a constructor");
        }
        return invokeAsConstructor(c, new Object[0], operand, context);
    }

    /**
     * Construct {@code callable} as if invoked via {@code new}. Used by
     * {@code Reflect.construct} which has no syntactic Node to thread through;
     * the engine creates a synthetic placeholder so event tracing has something
     * to attach to. Throws TypeError if the target is not constructable.
     */
    static Object constructFromHost(JsCallable callable, Object[] args, CoreContext context) {
        if (!callable.isConstructable()) {
            throw JsErrorException.typeError("target is not a constructor");
        }
        return invokeAsConstructor(callable, args, new Node(NodeType.NEW_EXPR), context);
    }

    private static Object invokeAsConstructor(JsCallable callable, Object[] args, Node node, CoreContext context) {

View on GitHub (pinned to a22eb90246)