nodejs/node · error

U_ILLEGAL_ESCAPE_SEQUENCE

U_ILLEGAL_ESCAPE_SEQUENCE

Error message

Bad escape: [%c%s]...

What it means

Emitted from the escape-parsing helper invoked while reading resource-bundle / rules text. u_unescapeAt returns the sentinel 0xFFFFFFFF when it cannot interpret the backslash escape beginning with character c1. With showWarning the raw offending context is printed; the helper then sets *error = U_ILLEGAL_ESCAPE_SEQUENCE and returns the lead character c1 without consuming the buffer.

Source

Thrown at deps/icu-small/source/tools/toolutil/ucbuf.cpp:429

    }

    /* Process the escape */
    offset = 0;
    c32 = u_unescapeAt(_charAt, &offset, length, (void*)buf);

    /* check if u_unescapeAt unescaped and converted
     * to c32 or not
     */
    if(c32==(UChar32)0xFFFFFFFF){
        if(buf->showWarning) {
            char context[CONTEXT_LEN+1];
            int32_t len = CONTEXT_LEN;
            if(length < len) {
                len = length; 
            }
            context[len]= 0 ; /* null terminate the buffer */
            u_UCharsToChars( buf->currentPos, context, len);
            fprintf(stderr,"Bad escape: [%c%s]...\n", (int)c1, context);
        }
        *error= U_ILLEGAL_ESCAPE_SEQUENCE;
        return c1;
    }else if(c32!=c2 || (c32==0x0075 && c2==0x0075 && c1==0x005C) /* for \u0075 c2=0x0075 and c32==0x0075*/){
        /* Update the current buffer position */
        buf->currentPos += offset;
    }else{
        /* unescaping failed so we just return
         * c1 and not consume the buffer
         * this is useful for rules with escapes
         * in resource bundles
         * eg: \' \\ \"
         */
        return c1;
    }

    return c32;
}

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Open the file at the reported offset and fix the escape: complete \uXXXX / \UXXXXXXXX with the correct number of hex digits.
  2. Use a literal backslash as \\ and quote other specials with the supported resource-bundle escapes (\' \\ \").
  3. Run the file through a JSON/ICU unescape linter (e.g. icu u_unescape round-trip) to flag every invalid escape before feeding it to the tool.
  4. If the backslash is intended literally in rule data, double-escape it (\\) so u_unescapeAt sees a valid sequence.

Example fix

// before (.txt resource bundle fragment):
//   "key" { "price \u12 each \q mark" }
// after:
//   "key" { "price \u0012 each \\q mark" }
Defensive patterns

Strategy: validation

Validate before calling

// Scan the text for backslash escapes u_unescapeAt would reject.
#include <unicode/unistr.h>
// Returns offset of the first bad escape, or -1.
int32_t first_bad_escape(const UChar* s, int32_t len) {
    for (int32_t i = 0; i < len; ++i) {
        if (s[i] == 0x5C /* \ */ && i + 1 < len) {
            UChar32 c0 = s[i + 1];
            // quick reject of escapes u_unescapeAt does not support
            const UChar ok[] = u"'\"\\abfnrtuUuxUN?"; // supported lead chars
            bool known = false;
            for (UChar o : ok) if (o == c0) { known = true; break; }
            if (!known) return i;
        }
    }
    return -1;
}

Try / catch

UErrorCode status = U_ZERO_ERROR;
// ... read UCHARBUF, call the escape-consuming API ...
if (status == U_ILLEGAL_ESCAPE_SEQUENCE) {
    // The 'Bad escape' line already named the lead char + context.
    // Report file/line and abort the resource build; do not mask it.
    return EXIT_FAILURE;
}

Prevention

When it happens

Trigger: A .txt resource bundle or rules file contains a malformed backslash escape: an unsupported escape like \q or \k; \x with non-hex digits (\xZZ); a truncated \u / \U with fewer than 4/8 hex digits (\u12, \U001); or any backslash sequence not in the resource-bundle escape set (\' \\ \").

Common situations: Hand-typed locale .txt files with typos in \uXXXX escapes; copy-paste that doubled or stripped backslashes; tooling that emitted non-hex digits after \u/\U/\x; a literal backslash in content that was not doubled.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/631ee46f2f54fc37. Report an issue: GitHub.