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

invalid escape sequence in template literal: \0

Error message

invalid escape sequence in template literal: \0<digit>

What it means

\0 followed by another decimal digit is an invalid legacy octal escape in template literals (ES spec early error), so the lexer rejects it. \0 alone (NUL) is fine, but \01, \05 etc. are not. Escape the digit separately or drop the extra digit.

Solutions

  1. Use just \0 and put the digit elsewhere (e.g. `\0` + String(i))
  2. Escape the backslash: `\\0${i}` if you want a literal backslash-zero then digit
  3. Use the explicit hex/codepoint escape \x00 or \u0000 instead of bare \0
  4. Reorder the string so a digit never directly follows the NUL escape

Example fix

// before
var rec = `row\05`;
// after
var rec = `row\u0000` + '5'; // or `row\x005` via concatenation
Defensive patterns

Strategy: validation

Validate before calling

if (/\\0[0-9]/.test(tpl)) throw new Error('\\0 followed by a digit is an invalid octal escape');

Type guard

null

Try / catch

try {
  karate.eval('var s = `' + tpl + '`;');
} catch (e) {
  if (String(e.message).indexOf('\\0') >= 0) {
    tpl = tpl.replace(/\\0(?=[0-9])/g, '\\u0000');
  } else throw e;
}

Prevention

When it happens

Trigger: A template literal contains \0 immediately followed by a digit, e.g. `\05` or an interpolated/built string like `prefix\0${i}` where the digit follows; detected at JsLexer.java:394 in scanTemplateContent.

Common situations: Building NUL-delimited strings with appended counters, porting C/old-JS octal escapes, generated payloads where \0 ends up adjacent to a digit, naive binary-data templates.

Related errors


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

Appendix: source

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

            }
            if (c == '$' && peek(1) == '{') {
                break;
            }
            if (c == '\\') {
                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))) {

View on GitHub (pinned to a22eb90246)