{"record":{"id":"6ebf5c17c46b07be","repo":"karatelabs/karate","slug":"regexp-prototype-tostring-called-on-incompatible-receiver","errorCode":null,"errorMessage":"RegExp.prototype.toString called on incompatible receiver","messagePattern":"RegExp\\.prototype\\.toString called on incompatible receiver","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsRegexPrototype.java","lineNumber":122,"sourceCode":"    }\n\n    private Object exec(Context context, Object[] args) {\n        return requireRegex(context, \"exec\").exec(argString(args, context));\n    }\n\n    private Object toStringMethod(Context context, Object[] args) {\n        Object thisObj = context.getThisObject();\n        // Spec §22.2.6.17 RegExp.prototype.toString reads `source` and `flags`\n        // via [[Get]] — works on any object that exposes them. JsRegex's\n        // toString matches that for the common case; fall back to the spec\n        // form when called on something else (e.g., a derived host object).\n        if (thisObj instanceof JsRegex r) return r.toString();\n        if (thisObj instanceof ObjectLike ol) {\n            CoreContext cc = context instanceof CoreContext c ? c : null;\n            return \"/\" + Terms.toStringCoerce(ol.getMember(\"source\"), cc) + \"/\"\n                    + Terms.toStringCoerce(ol.getMember(\"flags\"), cc);\n        }\n        throw JsErrorException.typeError(\"RegExp.prototype.toString called on incompatible receiver\");\n    }\n\n}\n","sourceCodeStart":104,"sourceCodeEnd":126,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsRegexPrototype.java#L104-L126","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nRegExp.prototype.toString.call(input)\n// after\nif (input instanceof RegExp) { input.toString() } else { String(input) }","handlingStrategy":"type-guard","validationCode":"if (typeof v === 'object' && v !== null && ('source' in v) && ('flags' in v)) { ... }","typeGuard":"function isRegExpLike(v) { return v instanceof RegExp || (typeof v === 'object' && v !== null && typeof v.source === 'string' && typeof v.flags === 'string'); }","tryCatchPattern":"try { return regexValue.toString(); } catch (e) { if (String(e).includes('incompatible receiver')) return String(regexValue); throw e; }","preventionTips":["Only call RegExp.prototype.toString on real RegExp instances.","Avoid unbound method extraction from RegExp.prototype.","When faking regexes, always supply source and flags."],"tags":["javascript","regexp","type-error"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}