karatelabs/karate · error · TypeError
RegExp.prototype.toString called on incompatible receiver
Error message
RegExp.prototype.toString called on incompatible receiver
What it means
RegExp.prototype.toString was called with a `this` that is neither a JsRegex nor an object exposing `source` and `flags` properties. The JS spec requires the receiver to be a RegExp-like object; anything else (a primitive, a function, etc.) is invalid.
Solutions
- Ensure toString is invoked on an actual RegExp value (e.g. /abc/.toString()).
- If calling unbound, pass a valid receiver: RegExp.prototype.toString.call(new RegExp('abc')).
- If using a plain object as a fake regex, provide string-valued `source` and `flags` members.
- Type-check the value before calling: only call .toString() when value instanceof RegExp.
Example fix
// before
RegExp.prototype.toString.call(input)
// after
if (input instanceof RegExp) { input.toString() } else { String(input) } Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof v === 'object' && v !== null && ('source' in v) && ('flags' in v)) { ... } Type guard
function isRegExpLike(v) { return v instanceof RegExp || (typeof v === 'object' && v !== null && typeof v.source === 'string' && typeof v.flags === 'string'); } Try / catch
try { return regexValue.toString(); } catch (e) { if (String(e).includes('incompatible receiver')) return String(regexValue); throw e; } Prevention
- Only call RegExp.prototype.toString on real RegExp instances.
- Avoid unbound method extraction from RegExp.prototype.
- When faking regexes, always supply source and flags.
When it happens
Trigger: Calling RegExp.prototype.toString via .call/.apply/bind with a non-RegExp `this`, e.g. RegExp.prototype.toString.call(42) or RegExp.prototype.toString.call(null).
Common situations: Generic utility code that assumes its argument is a regex but receives a number, string, or undefined; destructured or refactored code that lost the bound receiver; passing a regex-like plain object missing source/flags.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- AggregateError requires an iterable of errors
- Array.from requires an iterable or array-like object, not
- Array.prototype.* called on null or undefined
- BigInt.prototype method called on non-BigInt
- BigInts have no unsigned right shift, use >> instead
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/6ebf5c17c46b07be.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsRegexPrototype.java:122
}
private Object exec(Context context, Object[] args) {
return requireRegex(context, "exec").exec(argString(args, context));
}
private Object toStringMethod(Context context, Object[] args) {
Object thisObj = context.getThisObject();
// Spec §22.2.6.17 RegExp.prototype.toString reads `source` and `flags`
// via [[Get]] — works on any object that exposes them. JsRegex's
// toString matches that for the common case; fall back to the spec
// form when called on something else (e.g., a derived host object).
if (thisObj instanceof JsRegex r) return r.toString();
if (thisObj instanceof ObjectLike ol) {
CoreContext cc = context instanceof CoreContext c ? c : null;
return "/" + Terms.toStringCoerce(ol.getMember("source"), cc) + "/"
+ Terms.toStringCoerce(ol.getMember("flags"), cc);
}
throw JsErrorException.typeError("RegExp.prototype.toString called on incompatible receiver");
}
}
View on GitHub (pinned to a22eb90246)