karatelabs/karate · error · JsErrorException
Class extends value is not a constructor or null
Error message
Class extends value is not a constructor or null
What it means
Thrown when a `class A extends B` has a non-null, non-undefined B that is not a constructable ObjectLike callable. Per spec, the extends value must be a constructor or null; primitives, plain values, or non-constructable callables are rejected at class-definition time.
Solutions
- Ensure the extends expression is a class (or regular function) defined before the derived class is evaluated.
- If inheritance should be optional, use `extends null` explicitly rather than an undefined-resolving variable.
- Log/inspect the extends value's type; primitives and plain objects cannot be extended.
Example fix
// before
var base = { hello: 'world' };
class A extends base {}
// after
class Base {}
class A extends Base {} Defensive patterns
Strategy: validation
Validate before calling
if (Parent !== null && Parent !== undefined && (typeof Parent !== 'function')) throw new Error('extends value must be a constructor or null'); Type guard
function isValidExtends(v) { return v === null || v === undefined || typeof v === 'function'; } Try / catch
try { eval('class A extends ' + name + ' {}'); } catch (e) { /* falls back to default base class */ } Prevention
- Declare superclasses before derived classes
- Never extend primitives or plain objects
- Use `extends null` explicitly when intentionally baseless
When it happens
Trigger: Evaluating `class A extends X` where X is a number, string, boolean, plain object, arrow function, or any non-constructable value. `class A extends undefined` is explicitly allowed.
Common situations: Import/order issues where the superclass variable is still a placeholder value; typos in class names; transpiled code inheriting from something that was a function in another engine but is not constructable here.
Related errors
- Class constructor cannot be invoked without 'new
- 'super' keyword is only valid inside a class method
- super: parent class is not a constructor
- a class declaration may not be the body of
- a function declaration may not be the body of
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/8e909f337bcf298f.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/Interpreter.java:1074
}
// heritage: `extends <expr>` — the EXPR follows the EXTENDS token.
boolean hasExtends = false;
Object parentValue = null;
for (int i = 0, n = node.size(); i < n; i++) {
Node child = node.get(i);
if (child.token != null && child.token.type == EXTENDS) {
hasExtends = true;
parentValue = eval(node.get(i + 1), context);
break;
}
}
if (context.isError()) {
return Terms.UNDEFINED;
}
ObjectLike parentCtor = null;
if (hasExtends && parentValue != null && parentValue != Terms.UNDEFINED) {
if (!(parentValue instanceof JsCallable pc) || !pc.isConstructable() || !(parentValue instanceof ObjectLike)) {
throw JsErrorException.typeError("Class extends value is not a constructor or null");
}
parentCtor = (ObjectLike) parentValue;
}
Node ctorFnExpr = null;
List<ClassMember> members = new ArrayList<>();
for (int i = 0, n = node.size(); i < n; i++) {
Node child = node.get(i);
if (child.type == NodeType.CLASS_STATIC_BLOCK) {
// rides the member list so it interleaves with the static field
// initializers in source order
ClassMember block = new ClassMember();
block.isStatic = true;
block.staticBlock = child;
members.add(block);
continue;
}
if (child.type != NodeType.CLASS_METHOD) {
continue; // CLASS / EXTENDS / name / heritage EXPR / braces / semicolonsView on GitHub (pinned to a22eb90246)