{"record":{"id":"7a82df688c282e73","repo":"karatelabs/karate","slug":"regexp-escape-called-on-non-string","errorCode":null,"errorMessage":"RegExp.escape called on non-string","messagePattern":"RegExp\\.escape called on non-string","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsRegexConstructor.java","lineNumber":63,"sourceCode":"    }\n\n    @Override\n    public Object call(Context context, Object... args) {\n        if (args.length == 0) {\n            return new JsRegex();\n        }\n        String pattern = args[0].toString();\n        String flags = args.length > 1 ? args[1].toString() : \"\";\n        return new JsRegex(pattern, flags);\n    }\n\n    // RegExp.escape (ES2025). Spec §22.2.7.1: TypeError on non-String input;\n    // walks code points, prefixes leading digit/letter with \\x##, otherwise\n    // delegates each code point to EncodeForRegExpEscape.\n    private Object escape(Object[] args) {\n        Object s = args.length > 0 ? args[0] : Terms.UNDEFINED;\n        if (!(s instanceof String str)) {\n            throw JsErrorException.typeError(\"RegExp.escape called on non-string\");\n        }\n        StringBuilder out = new StringBuilder(str.length() + 8);\n        for (int i = 0; i < str.length(); ) {\n            int cp = str.codePointAt(i);\n            if (out.length() == 0 && isAsciiDigitOrLetter(cp)) {\n                out.append(\"\\\\x\").append(toHexLowerPad(cp, 2));\n            } else {\n                encodeForRegExpEscape(out, cp);\n            }\n            i += Character.charCount(cp);\n        }\n        return out.toString();\n    }\n\n    private static boolean isAsciiDigitOrLetter(int cp) {\n        return (cp >= '0' && cp <= '9') || (cp >= 'A' && cp <= 'Z') || (cp >= 'a' && cp <= 'z');\n    }\n","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsRegexConstructor.java#L45-L81","documentation":"RegExp.escape (ES2025) requires a String argument per spec §22.2.7.1 — it does not coerce. Karate throws a TypeError 'RegExp.escape called on non-string' when the first argument is missing, undefined, or any non-string value (number, object, etc.).","triggerScenarios":"RegExp.escape(); RegExp.escape(42); RegExp.escape(userValue) where userValue is a number or null; relying on implicit ToString coercion that the spec forbids.","commonSituations":"Escaping user input for safe interpolation into a RegExp before checking its type; passing match-array captures (which can be undefined) or numbers from form/API data directly to RegExp.escape.","solutions":["Convert explicitly first: RegExp.escape(String(value))","Guard with typeof value === 'string' before calling, and handle non-strings separately","Provide a default: RegExp.escape(value ?? '')"],"exampleFix":"// before\nconst safe = RegExp.escape(userInput); // may be a number\n// after\nconst safe = typeof userInput === 'string' ? RegExp.escape(userInput) : '';","handlingStrategy":"type-guard","validationCode":"if (typeof v !== 'string') throw new Error('RegExp.escape requires a string, got: ' + typeof v);\nconst safe = RegExp.escape(v);","typeGuard":"const isStr = v => typeof v === 'string';\nconst safeEscape = v => isStr(v) ? RegExp.escape(v) : RegExp.escape(String(v));","tryCatchPattern":"try {\n  return RegExp.escape(value);\n} catch (e) {\n  if (String(e.message).includes('non-string')) {\n    return RegExp.escape(String(value));\n  }\n  throw e;\n}","preventionTips":["Coerce with String(value) before escaping when input type is uncertain","Handle undefined captures/nulls from match results before escaping","Never rely on implicit ToString coercion for spec-strict builtins","Validate user-supplied values at the boundary before regex construction"],"tags":["javascript","regexp","typeerror","escape"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}