karatelabs/karate · error · io.karatelabs.parser.ParserException

invalid hex escape sequence in template literal

Error message

invalid hex escape sequence in template literal

What it means

\x in a template literal must be followed by exactly two hex digits (\xHH); anything else is an invalid hex escape and the lexer throws. This is an ES-spec early error for untagged templates, enforced at lex time by karate-js.

Solutions

  1. Pad the hex escape to two digits: \x0a instead of \xa or \x1
  2. Escape the backslash if you meant a literal one: `\\xml`
  3. Use \u00XX form if you need a single-digit codepoint
  4. Verify the intended character code and rewrite the escape

Example fix

// before
var nl = `a\xb`;        // only one hex digit
var tag = `\xml data`;  // \x followed by 'm'
// after
var nl = `a\x0b`;
var tag = `\\xml data`;
Defensive patterns

Strategy: validation

Validate before calling

// ensure every \x is followed by exactly two hex digits
function hasBadHexEscape(tpl) {
  var m = tpl.match(/\\x[0-9a-fA-F]{0,2}/g) || [];
  return m.some(function (s) { return s.length !== 4; }) || /\\x(?![0-9a-fA-F]{2})/.test(tpl);
}
if (hasBadHexEscape(tpl)) throw new Error('bad \\x escape in template literal');

Type guard

null

Try / catch

try {
  karate.eval('var s = `' + tpl + '`;');
} catch (e) {
  if (String(e.message).indexOf('invalid hex escape') >= 0) {
    tpl = tpl.replace(/\\x/g, '\\u00'); // promote to \u00NN form where possible
  } else throw e;
}

Prevention

When it happens

Trigger: Template literal contains \x not followed by two hex digits, e.g. `\x1`, `\xg`, `\x`, or a Windows path/regex fragment like `\xml` inside backticks; thrown at JsLexer.java:399.

Common situations: Half-written hex escapes, file extensions or tags after a backslash (\xml, \xlsx), copy-pasted snippets from languages with different escape rules, regex patterns pasted into template strings.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/parser/JsLexer.java:399

                advance();
                if (isAtEnd()) {
                    break;
                }
                char esc = peek();
                // Spec: in non-tagged template literals, malformed escape sequences are
                // early errors. We have no way to tell tag vs no-tag at lex time, so we
                // reject at lex time; tagged templates are not yet supported anyway.
                // Invalid legacy octal: \1..\9 or \0 followed by a decimal digit.
                if (esc >= '1' && esc <= '9') {
                    throw new ParserException("invalid escape sequence in template literal: \\" + esc);
                }
                if (esc == '0' && peek(1) >= '0' && peek(1) <= '9') {
                    throw new ParserException("invalid escape sequence in template literal: \\0" + peek(1));
                }
                // Hex escape backslash-x HH — require exactly two hex digits.
                if (esc == 'x') {
                    if (!isHexDigit(peek(1)) || !isHexDigit(peek(2))) {
                        throw new ParserException("invalid hex escape sequence in template literal");
                    }
                }
                // Unicode escape backslash-u HHHH or backslash-u {H...} — require proper form.
                if (esc == 'u') {
                    char next = peek(1);
                    if (next == '{') {
                        // backslash-u { codepoint } — one or more hex digits, closed by }
                        int j = 2;
                        if (!isHexDigit(peek(j))) {
                            throw new ParserException("invalid unicode escape sequence in template literal");
                        }
                        int codepoint = 0;
                        while (isHexDigit(peek(j))) {
                            char h = peek(j);
                            int v = (h >= '0' && h <= '9') ? h - '0'
                                    : (h >= 'a' && h <= 'f') ? h - 'a' + 10
                                    : h - 'A' + 10;
                            codepoint = (codepoint << 4) | v;

View on GitHub (pinned to a22eb90246)