karatelabs/karate · error · JsErrorException

Reflect.construct: newTarget is not a constructor

Error message

Reflect.construct: newTarget is not a constructor

What it means

When `Reflect.construct` is given a third argument (newTarget), the engine verifies it is a JsCallable and a valid constructor, since newTarget determines the result's [[Prototype]]. Passing a present-but-non-callable third argument throws this TypeError before any construction happens.

Solutions

  1. Pass a constructable function/class as newTarget, or omit the third argument to reuse target.
  2. Guard: `if (newTarget && typeof newTarget === 'function') Reflect.construct(T, a, newTarget) else Reflect.construct(T, a)`.
  3. Verify the subclass registry entry actually holds a class, not an instance.

Example fix

// before
const obj = Reflect.construct(Base, args, registry[name]); // registry entry missing -> undefined
// after
const NT = registry[name];
const obj = typeof NT === 'function' ? Reflect.construct(Base, args, NT) : Reflect.construct(Base, args);
Defensive patterns

Strategy: validation

Validate before calling

function safeConstructWithTarget(Target, args, NewTarget) {
  const useNT = typeof NewTarget === 'function' && NewTarget.prototype;
  return useNT ? Reflect.construct(Target, args, NewTarget) : Reflect.construct(Target, args);
}

Type guard

function isValidNewTarget(v) { return v != null && typeof v === 'function' && !!v.prototype; }

Try / catch

try { return Reflect.construct(T, a, NT); } catch (e) { if (e instanceof TypeError && /newTarget is not a constructor/.test(e.message)) return Reflect.construct(T, a); throw e; }

Prevention

When it happens

Trigger: `Reflect.construct(Target, args, notAFunction)` — e.g. passing an object, a primitive, or an undefined variable as newTarget.

Common situations: Metaprogramming that computes newTarget dynamically (subclass registries, plugin systems) where the lookup returned a non-function; typos in the third argument.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsReflect.java:85

    protected Iterable<String> ownIntrinsicNames() {
        return INTRINSIC_NAMES;
    }

    // Reflect.construct(target, argumentsList[, newTarget])
    // Spec §28.1.2: throws TypeError if target or newTarget is not a constructor;
    // dispatches Construct(target, args, newTarget). For our minimal version,
    // newTarget mostly affects the result's [[Prototype]] — the test262
    // isConstructor harness only cares whether the call throws, so we use
    // newTarget purely as the constructable check when supplied.
    private Object construct(Context context, Object[] args) {
        if (args.length < 1 || !(args[0] instanceof JsCallable target)) {
            throw JsErrorException.typeError("Reflect.construct: target is not a constructor");
        }
        Object[] cArgs = listToArray(args.length >= 2 ? args[1] : null);
        JsCallable check = target;
        if (args.length >= 3) {
            if (!(args[2] instanceof JsCallable nt)) {
                throw JsErrorException.typeError("Reflect.construct: newTarget is not a constructor");
            }
            check = nt;
        }
        if (!check.isConstructable()) {
            throw JsErrorException.typeError("Reflect.construct: target is not a constructor");
        }
        if (!(context instanceof CoreContext cc)) {
            throw JsErrorException.typeError("Reflect.construct: bad context");
        }
        return Interpreter.constructFromHost(target, cArgs, cc);
    }

    // Reflect.apply(target, thisArgument, argumentsList) — spec §28.1.1.
    private Object apply(Context context, Object[] args) {
        if (args.length < 1 || !(args[0] instanceof JsCallable target)) {
            throw JsErrorException.typeError("Reflect.apply: target is not callable");
        }
        Object thisArg = args.length >= 2 ? args[1] : Terms.UNDEFINED;

View on GitHub (pinned to a22eb90246)