nodejs/node · error
U_ILLEGAL_CHAR_FOUND
U_ILLEGAL_CHAR_FOUND
Error message
Illegal Surrogate!
What it means
While converting Unicode strings to XML-escaped UTF-8 for XLIFF output, genrb encountered an unpaired surrogate code unit. U16_NEXT extracted a value in the surrogate range (U+D800–U+DFFF) that is not part of a valid surrogate pair. XML cannot represent lone surrogates, so the conversion aborts with U_ILLEGAL_CHAR_FOUND.
Source
Thrown at deps/icu-small/source/tools/genrb/wrtxml.cpp:263
}
dest =*pDest;
if(dest==nullptr || destCap <=0){
destCap = srcLen * 8;
dest = static_cast<char*>(uprv_malloc(sizeof(char) * destCap));
if(dest==nullptr){
*status=U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
}
dest[0]=0;
while(srcIndex<srcLen){
U16_NEXT(src, srcIndex, srcLen, c);
if (U16_IS_LEAD(c) || U16_IS_TRAIL(c)) {
*status = U_ILLEGAL_CHAR_FOUND;
fprintf(stderr, "Illegal Surrogate! \n");
uprv_free(dest);
return nullptr;
}
if((destLen+U8_LENGTH(c)) < destCap){
/* ASCII Range */
if(c <=0x007F){
switch(c) {
case '\x26':
uprv_strcpy(dest+( destLen),"\x26\x61\x6d\x70\x3b"); /* &*/
destLen += static_cast<int32_t>(uprv_strlen("\x26\x61\x6d\x70\x3b"));
break;
case '\x3c':
uprv_strcpy(dest+(destLen),"\x26\x6c\x74\x3b"); /* <*/
destLen += static_cast<int32_t>(uprv_strlen("\x26\x6c\x74\x3b"));
break;
case '\x3e':View on GitHub (pinned to 1b2de5e052)
Solutions
- Find the string with the lone surrogate — genrb should indicate which bundle/file is being processed when this occurs
- Validate the resource bundle .txt file for lone surrogates: `grep -P '[\x{D800}-\x{DFFF}]' <file.txt>`
- Replace the lone surrogate with the correct supplementary character (use the full \Uxxxxxxxx escape) or remove it
- If the source is generated, fix the generator to emit proper UTF-16 surrogate pairs or UTF-8 directly
- Use ICU's u_strToUTF8 or icu::UnicodeString to detect and repair malformed surrogates before feeding to genrb
Example fix
// before: lone surrogate in resource string
greeting { "Hello \uD800" }
// after: complete supplementary character or removal
greeting { "Hello \U00010000" } Defensive patterns
Strategy: validation
Validate before calling
# Scan resource bundle files for lone surrogates before genrb
for f in data/*.txt; do
# Check for \uD8xx-\uDBxx not followed by \uDCxx-\uDFxx (lone high surrogate)
# and \uDCxx-\uDFxx not preceded by high surrogate (lone low surrogate)
python3 -c "
import re, sys
text = open(sys.argv[1], encoding='utf-8').read()
# Find all unicode escape sequences
escapes = re.findall(r'\\\\u([0-9A-Fa-f]{4})', text)
codepoints = [int(e, 16) for e in escapes]
for i, cp in enumerate(codepoints):
if 0xD800 <= cp <= 0xDBFF: # high surrogate
if i+1 >= len(codepoints) or not (0xDC00 <= codepoints[i+1] <= 0xDFFF):
print(f'Lone high surrogate at escape index {i}: U+{cp:04X}')
elif 0xDC00 <= cp <= 0xDFFF: # low surrogate
if i == 0 or not (0xD800 <= codepoints[i-1] <= 0xDBFF):
print(f'Lone low surrogate at escape index {i}: U+{cp:04X}')
" "$f"
done Prevention
- Validate all Unicode escape sequences in resource bundles form proper surrogate pairs
- Use \Uxxxxxxxx escapes for supplementary characters instead of manual surrogate pairs
- Ensure text editors and transfer tools preserve proper UTF encoding without splitting surrogates
- Run a Unicode validation check on resource bundle files before building
When it happens
Trigger: A string in the resource bundle contains a lone high surrogate (U+D800–U+DBFF) not followed by a low surrogate, or a lone low surrogate (U+DC00–U+DFFF) not preceded by a high surrogate. This passes through genrb's parser but fails during the XML output stage because XML requires well-formed UTF.
Common situations: String was truncated mid-surrogate-pair during editing or transfer; a supplementary character was incorrectly split across string concatenation boundaries; UTF-16 file corrupted at a surrogate boundary; resource bundle generated by tooling that doesn't properly handle supplementary characters.
Related errors
- An error occurred processing file %s. Error: %s
- An error occurred processing file %s. Error: %s
- Could not canonicalize the locale ID: %s. Error: %s
- U_MEMORY_ALLOCATION_ERROR
- U_ILLEGAL_ARGUMENT_ERROR
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/2dba660d0554dd2e.
Report an issue: GitHub.