karatelabs/karate · error · JsErrorException

Reflect.construct: target is not a constructor

Error message

Reflect.construct: target is not a constructor

What it means

`Reflect.construct(target, args)` requires `target` to be a constructable function; the engine also re-checks constructability on `newTarget` when supplied. If args[0] is absent or not a JsCallable (or the effective constructor fails `isConstructable()`), this TypeError is thrown, matching the spec's IsConstructor check.

Solutions

  1. Pass a constructable function/class as target: `Reflect.construct(MyClass, args)`.
  2. Guard: `if (typeof Target === 'function' && Target.prototype) Reflect.construct(Target, args)`.
  3. If the target is an arrow function, convert to a regular function/class.

Example fix

// before
const instance = Reflect.construct(arrowFactory, [opts]); // arrow is not constructable
// after
function Factory(opts) { this.opts = opts; }
const instance = Reflect.construct(Factory, [opts]);
Defensive patterns

Strategy: type-guard

Validate before calling

function safeConstruct(Target, args) {
  if (typeof Target !== 'function' || !Target.prototype) throw new TypeError('target must be a constructor');
  return Reflect.construct(Target, args);
}

Type guard

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

Try / catch

try { return Reflect.construct(Target, args); } catch (e) { if (e instanceof TypeError && /target is not a constructor/.test(e.message)) return Target.apply(null, args); throw e; }

Prevention

When it happens

Trigger: `Reflect.construct()` with no target; `Reflect.construct(someObject, [])`; `Reflect.construct(arrowFn, [])` (arrows aren't constructable); passing a non-constructable built-in.

Common situations: Dynamic class instantiation from configuration where the target lookup resolved to undefined or an arrow function; reflection-based factories over non-constructable values.

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/5e1c0c5513da19ef. Report an issue: GitHub.

Appendix: source

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

            keys.addAll(jo.ownSymbols());
        }
        return new JsArray(keys);
    }

    @Override
    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);
    }

View on GitHub (pinned to a22eb90246)