karatelabs/karate · error · JsErrorException
Constructor Map requires 'new'
Error message
Constructor Map requires 'new'
What it means
The Map constructor was invoked without `new` (e.g. `Map()` instead of `new Map()`). Karate's JS engine checks callInfo.constructor in JsMapConstructor.call and throws a TypeError because built-in constructors like Map cannot be called as plain functions (unlike, say, Object or Array).
Solutions
- Add the `new` keyword: `new Map()`.
- If you need call-or-construct flexibility, write `var m = x instanceof Map ? x : new Map(...)`.
- Ensure callbacks/wrappers that create maps use Reflect-style construction or an explicit arrow returning `new Map(...)`.
- Audit for other built-ins (WeakMap, Set) that share the same requirement.
Example fix
// before var m = Map(entries); // TypeError // after var m = new Map(entries);
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof Map !== 'function') throw new Error('Map unavailable'); // construction sites must use new Type guard
function isMap(v) { return v instanceof Map; } Try / catch
try { var m = makeMap(entries); } catch (e) { if (String(e).indexOf("requires 'new'") !== -1) { var m2 = new Map(entries); } else { throw e; } } Prevention
- Always invoke built-in constructors (Map, Set, WeakMap) with new
- Never pass the constructor itself as a plain callback
- Wrap construction in helper functions that enforce new internally
When it happens
Trigger: Calling Map() directly; passing Map as a callback where `new` semantics are lost (e.g. arr.map(Map)); refactors that dropped the `new` keyword; calling it through a wrapper that invokes without constructor context.
Common situations: Porting code patterns where new was optional for other constructors; default-parameter fallbacks like `options.map || Map()`; transpiled/minified code that stripped `new`.
Related errors
- is not a constructor
- Class constructor cannot be invoked without 'new
- Map.prototype.set is not callable
- Iterator value is not an entry object
- Method Map.prototype called on incompatible receiver
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/7d168dd2395a6308.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsMapConstructor.java:62
defineOwn("prototype", JsMapPrototype.INSTANCE, PropertySlot.INTRINSIC);
defineOwn("groupBy", new JsBuiltinMethod("groupBy", 2, (JsCallable) this::groupBy), METHOD_ATTRS);
}
private Object groupBy(Context context, Object[] args) {
Object items = args.length > 0 ? args[0] : Terms.UNDEFINED;
Object callback = args.length > 1 ? args[1] : Terms.UNDEFINED;
// Spec: result is a fresh Map; keys carry -0 → +0 normalization (zero
// coercion mode) — verified by negativeZero.js.
return GroupByImpl.toMap(
GroupByImpl.run(items, callback, /* propertyMode= */ false, context));
}
@Override
public Object call(Context context, Object[] args) {
CallInfo callInfo = context.getCallInfo();
boolean isNew = callInfo != null && callInfo.constructor;
if (!isNew) {
throw JsErrorException.typeError("Constructor Map requires 'new'");
}
JsMap map = new JsMap();
if (args.length == 0 || args[0] == null || args[0] == Terms.UNDEFINED) {
return map;
}
// Look up `set` on the freshly-constructed map's prototype chain — honors
// user-overridden Map.prototype.set per spec 24.1.1.1 step 9.
Object setFn = map.getMember("set");
if (!(setFn instanceof JsCallable adder)) {
throw JsErrorException.typeError("Map.prototype.set is not callable");
}
JsIterator iter = IterUtils.getIterator(args[0], context);
CoreContext cc = context instanceof CoreContext c ? c : null;
Object savedThis = cc != null ? cc.thisObject : null;
try {
while (iter.hasNext()) {
Object entry = iter.next();
if (!(entry instanceof List) && !(entry instanceof ObjectLike)) {View on GitHub (pinned to a22eb90246)