toon-format/toon · error · SyntaxError

Invalid escape sequence: \u must be followed by 4 hex digits

Error message

Invalid escape sequence: \u must be followed by 4 hex digits, got "${hex}"

What it means

After \u, the next 4 characters must be hexadecimal digits. If they are not (e.g. \uZZZZ or \u 12), unescapeString throws this SyntaxError reporting the offending 4-character slice.

Source

Thrown at packages/toon/src/shared/string-utils.ts:90

        continue
      }
      if (next === BACKSLASH) {
        unescaped += BACKSLASH
        i += 2
        continue
      }
      if (next === DOUBLE_QUOTE) {
        unescaped += DOUBLE_QUOTE
        i += 2
        continue
      }
      if (next === 'u') {
        if (i + 6 > value.length) {
          throw new SyntaxError(`Invalid escape sequence: truncated \\u escape at "${value.slice(i, i + 6)}"`)
        }
        const hex = value.slice(i + 2, i + 6)
        if (!/^[0-9a-f]{4}$/i.test(hex)) {
          throw new SyntaxError(`Invalid escape sequence: \\u must be followed by 4 hex digits, got "${hex}"`)
        }
        const codeUnit = Number.parseInt(hex, 16)
        if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
          throw new SyntaxError(`Invalid escape sequence: \\u${hex} is a lone surrogate. Supplementary code points MUST appear as literal UTF-8`)
        }
        unescaped += String.fromCodePoint(codeUnit)
        i += 6
        continue
      }

      throw new SyntaxError(`Invalid escape sequence: \\${next}`)
    }

    unescaped += value[i]
    i++
  }

  return unescaped

View on GitHub (pinned to 604eac266e)

Solutions

  1. Correct the escape to exactly 4 hex digits 0-9/a-f/A-F
  2. Replace the escape with the literal UTF-8 character
  3. Escape non-ASCII content when encoding rather than hand-writing \u escapes

Example fix

// before (TOON input)
name: "\u1G3F"
// after
name: "\u1F3F"  // or the literal emoji character
Defensive patterns

Strategy: validation

Validate before calling

function hasValidUnicodeEscapes(s: string): boolean {
  return !/\\u(?:(?![0-9a-fA-F]{4})|(?![0-9a-fA-F]{4}))/i.test(s.replace(/\\u[0-9a-fA-F]{4}/g, ''))
}

Try / catch

try {
  const value = decode(input)
} catch (e) {
  if (e instanceof SyntaxError && e.message.includes('4 hex digits')) {
    // extract offending hex from message, correct, retry
  }
  throw e
}

Prevention

When it happens

Trigger: Parsing a quoted TOON string containing \u followed by 4 non-hex characters, e.g. "\u1G3F" or "\u hEL".

Common situations: Hand-written escapes with typos; strings converted from formats allowing surrogate-pair escapes; generated input where placeholders leaked into \u sequences.

Related errors


AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31). Data as JSON: /api/errors/2aa70cb0915d4987. Report an issue: GitHub.