karatelabs/karate · error · TypeError

Reflect.construct: bad context

Error message

Reflect.construct: bad context

What it means

After validating the target/newTarget are constructable, JsReflect.construct requires the active interpreter Context to be an instance of CoreContext so it can dispatch Interpreter.constructFromHost. If the surrounding Context is some other Context implementation, a TypeError 'Reflect.construct: bad context' is thrown. This is effectively an internal invariant violation — normal Karate JS evaluation always provides a CoreContext.

Solutions

  1. Run the script through the standard Karate JS engine entry point so a CoreContext is active
  2. If embedding, ensure the Context passed to JsCallable.call is the engine's CoreContext, not a custom subclass/wrapper
  3. Upgrade or re-align custom Context implementations after engine version changes
Defensive patterns

Strategy: validation

Validate before calling

// Host-side check before invoking the engine builtin:
if (!(context instanceof io.karatelabs.js.CoreContext)) {
    throw new IllegalStateException('Reflect.construct requires a CoreContext');
}

Type guard

if (!(context instanceof io.karatelabs.js.CoreContext cc)) {
    throw new IllegalStateException('bad context: ' + context.getClass().getName());
}

Try / catch

try {
    return Reflect_construct(ctx, args);
} catch (JsErrorException e) {
    if (e.getMessage().contains("bad context")) {
        // re-run through the standard engine entry point
        return engine.eval(scriptWithContextFixed);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling Reflect.construct from a context where `context instanceof CoreContext` is false — e.g. embedding the Karate JS engine and invoking builtins with a custom/minimal Context implementation rather than the engine's CoreContext.

Common situations: Embedding karate-js in a host application with a hand-rolled Context; calling engine internals reflectively or from a custom host-object callback that supplies its own Context; version drift where a custom Context was written against an older engine that did not require CoreContext here.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

    // 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;
        Object[] cArgs = listToArray(args.length >= 3 ? args[2] : null);
        if (context instanceof CoreContext cc) {
            cc.thisObject = thisArg;
        }
        return target.call(context, cArgs);
    }

    private static Object[] listToArray(Object value) {

View on GitHub (pinned to a22eb90246)