karatelabs/karate · error · TypeError

RegExp.escape called on non-string

Error message

RegExp.escape called on non-string

What it means

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.).

Solutions

  1. Convert explicitly first: RegExp.escape(String(value))
  2. Guard with typeof value === 'string' before calling, and handle non-strings separately
  3. Provide a default: RegExp.escape(value ?? '')

Example fix

// before
const safe = RegExp.escape(userInput); // may be a number
// after
const safe = typeof userInput === 'string' ? RegExp.escape(userInput) : '';
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof v !== 'string') throw new Error('RegExp.escape requires a string, got: ' + typeof v);
const safe = RegExp.escape(v);

Type guard

const isStr = v => typeof v === 'string';
const safeEscape = v => isStr(v) ? RegExp.escape(v) : RegExp.escape(String(v));

Try / catch

try {
  return RegExp.escape(value);
} catch (e) {
  if (String(e.message).includes('non-string')) {
    return RegExp.escape(String(value));
  }
  throw e;
}

Prevention

When it happens

Trigger: RegExp.escape(); RegExp.escape(42); RegExp.escape(userValue) where userValue is a number or null; relying on implicit ToString coercion that the spec forbids.

Common situations: 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.

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


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/7a82df688c282e73. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsRegexConstructor.java:63

    }

    @Override
    public Object call(Context context, Object... args) {
        if (args.length == 0) {
            return new JsRegex();
        }
        String pattern = args[0].toString();
        String flags = args.length > 1 ? args[1].toString() : "";
        return new JsRegex(pattern, flags);
    }

    // RegExp.escape (ES2025). Spec §22.2.7.1: TypeError on non-String input;
    // walks code points, prefixes leading digit/letter with \x##, otherwise
    // delegates each code point to EncodeForRegExpEscape.
    private Object escape(Object[] args) {
        Object s = args.length > 0 ? args[0] : Terms.UNDEFINED;
        if (!(s instanceof String str)) {
            throw JsErrorException.typeError("RegExp.escape called on non-string");
        }
        StringBuilder out = new StringBuilder(str.length() + 8);
        for (int i = 0; i < str.length(); ) {
            int cp = str.codePointAt(i);
            if (out.length() == 0 && isAsciiDigitOrLetter(cp)) {
                out.append("\\x").append(toHexLowerPad(cp, 2));
            } else {
                encodeForRegExpEscape(out, cp);
            }
            i += Character.charCount(cp);
        }
        return out.toString();
    }

    private static boolean isAsciiDigitOrLetter(int cp) {
        return (cp >= '0' && cp <= '9') || (cp >= 'A' && cp <= 'Z') || (cp >= 'a' && cp <= 'z');
    }

View on GitHub (pinned to a22eb90246)