karatelabs/karate · error · JsErrorException

super: parent class is not a constructor

Error message

super: parent class is not a constructor

What it means

Thrown when running a derived constructor's `super(...)` but the derived class's prototype (its [[Prototype]], set to the superclass at class-eval time) is not a constructable JsCallable. This happens when the extends chain was corrupted or the parent was replaced with a non-constructor value.

Solutions

  1. Do not reassign the parent class binding after the derived class is declared.
  2. Re-derive the child class from a valid constructor: `class Child extends ValidParent {}`.
  3. Check for Object.setPrototypeOf calls or factory code that replaced the parent with a plain object.

Example fix

// before
let Parent = {};
class Child extends Parent {}
// after
class Parent {}
class Child extends Parent {}
Defensive patterns

Strategy: validation

Validate before calling

if (typeof ParentClass !== 'function') throw new Error('parent class must be a constructable function');

Type guard

function isClassLike(v) { return typeof v === 'function' && v.prototype && v.prototype.constructor === v; }

Try / catch

try { var c = new Child(); } catch (e) { if (String(e).includes('parent class is not a constructor')) restoreParent(); }

Prevention

When it happens

Trigger: Instantiating a derived class whose parent class reference was overwritten with a non-constructable value, or whose [[Prototype]] was mutated (e.g. Object.setPrototypeOf) to a non-callable.

Common situations: Monkey-patching or reassigning a class binding after definition; circular or partially-initialized class definitions where the parent ended up undefined or an object.

Related errors


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

Appendix: source

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

        }
        if (thisObj instanceof JsSet dst && built instanceof JsSet src) {
            dst.elements.putAll(src.elements);
            return true;
        }
        if (thisObj instanceof JsDate dst && built instanceof JsDate src) {
            dst.setTimeValue(src.getTimeValue());
            return true;
        }
        return false;
    }

    // Runs the parent constructor of {@code derivedCtor} against an existing
    // instance ({@code thisObj}) — the derived `this`. The parent is the derived
    // constructor's [[Prototype]] (set to the superclass at class-eval time).
    static void runSuperConstructor(JsFunctionNode derivedCtor, Object thisObj, Object[] args, CoreContext context) {
        Object parent = derivedCtor.getPrototype(); // Child.__proto__ === Parent
        if (!(parent instanceof JsCallable parentCallable) || !parentCallable.isConstructable()) {
            throw JsErrorException.typeError("super: parent class is not a constructor");
        }
        if (parent instanceof JsFunctionNode parentFn) {
            CoreContext sc = new CoreContext(context, parentFn.node, args,
                    parentFn.declaredContext, parentFn.capturedBindings);
            sc.strict = parentFn.strict;
            sc.thisObject = thisObj;
            sc.activeFunction = parentFn;
            sc.callInfo = new CallInfo(true, parentFn);
            sc.privateEnv = parentFn.privateEnv;
            // If the parent is itself a derived class with an implicit
            // constructor, forward up the chain before running its (empty) body.
            // Either way the parent's own instance fields (and private brands) are
            // its responsibility, on the same before-body / after-super schedule the
            // top-level construction path uses; a parent with an explicit derived
            // constructor runs them from its own super() call instead.
            if (parentFn.isDefaultDerivedConstructor) {
                runSuperConstructor(parentFn, thisObj, args, sc);
                runInstanceFieldInitializers(parentFn, thisObj, sc);

View on GitHub (pinned to a22eb90246)