karatelabs/karate · error · JsErrorException

target is not a constructor

Error message

target is not a constructor

What it means

Thrown by `Reflect.construct` support when the target callable lacks a [[Construct]] slot. `constructFromHost` is the host-side path for Reflect.construct with no syntactic `new` node, so the message names the 'target' argument per the spec. This mirrors V8's `Reflect.construct: target is not a constructor` TypeError.

Solutions

  1. Check `Reflect.construct`'s first argument is a class or regular function before calling it.
  2. Guard with a typeof/isFunction check and fall back to a normal call if not constructable.
  3. Fix resolution logic so the intended class (not an arrow function or import default) is passed.

Example fix

// before
var o = Reflect.construct(makeThing, []);
// after
var Thing = resolveClass();
if (typeof Thing !== 'function') throw new Error('expected a class');
var o = Reflect.construct(Thing, []);
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof target !== 'function') throw new Error('Reflect.construct target must be a constructor');

Type guard

function isConstructableTarget(v) { return typeof v === 'function' && !/=>/.test(String(v)); }

Try / catch

try { return Reflect.construct(target, args); } catch (e) { if (String(e).includes('not a constructor')) return null; throw e; }

Prevention

When it happens

Trigger: Calling `Reflect.construct(target, args)` (or host code invoking Interpreter.constructFromHost) where target is an arrow function, a method, a bound non-constructable callable, or a plain object.

Common situations: Utility code that dynamically instantiates classes via Reflect.construct receiving user-supplied or resolved-at-runtime values that turn out not to be classes.

Related errors


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

Appendix: source

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

        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) {
        CoreContext callContext;
        ObjectLike newInstance = null;
        Object result;
        if (callable instanceof JsFunctionNode jsFunc) {
            callContext = new CoreContext(context, node, args, jsFunc.declaredContext, jsFunc.capturedBindings);
            callContext.strict = jsFunc.strict;
            callContext.callInfo = new CallInfo(true, callable);
            callContext.privateEnv = jsFunc.privateEnv;
            callContext.activeFunction = jsFunc;
            newInstance = allocateInstance(jsFunc);
            Object proto = jsFunc.getMember("prototype");
            if (proto instanceof ObjectLike protoObj) {
                setInstancePrototype(newInstance, protoObj);

View on GitHub (pinned to a22eb90246)