# Fix the formatjs ICU message syntax error on an unexpected token

## TL;DR

The ICU parser hit a character it did not expect at a specific offset, so get that offset and look there first. The usual suspects are a stray apostrophe, which starts quoted text in ICU, or a brace that never closes. Fix the character, re-parse, and move on.

## The error

```text
SyntaxError: Unexpected token at offset 24
message: "You\u0027ve got {count, plural, one {# message} other {# messages}}"
the doubled quote above is the correct escape, a single quote breaks parsing
```

## Fix it

### Step 1: Reproduce the parse failure with the exact string

```bash
node -e "const {parse}=require('@formatjs/icu-messageformat-parser'); parse(process.argv[1])" "You've got {count, plural, one {# message} other {# messages}}"
```

Expected: The parser throws and names the offset.

### Step 2: Inspect the character at that offset

```bash
node -e "const s=process.argv[1]; const i=24; console.log(JSON.stringify(s.slice(i-6,i+6)))" "You've got {count, plural, one {# message} other {# messages}}"
```

Expected: You see the offending character in context.

### Step 3: Fix it: double apostrophes, balance braces

```bash
node -e "console.log('write You\u0027\u0027ve for a literal apostrophe in ICU')"
```

Expected: The corrected string parses cleanly.

### Step 4: Add the message to your extract lint so it stays fixed

```bash
npx formatjs extract 'src/**/*.js' --out-file /tmp/check.json | tail -3
```

Expected: Extraction completes with no syntax errors.

## When to use this

- formatjs throws SyntaxError or unexpected token while parsing a message
- A message with apostrophes or quotes fails to parse

## When NOT to use this

- The message parses but selects the wrong plural, check locale data
- The error is at runtime in the browser, make sure the parser version matches the runtime

## Tool and version compatibility

- @formatjs/icu-messageformat-parser v1/v2, react-intl v5+
- ICU MessageFormat as implemented by formatjs, not Java MessageFormat

## Variant phrasings

### unexpected token inside a select block

Same approach. Select blocks need an other case, a missing one often reads as an unexpected token at the end.

### error only in one locale file

Translators edited the ICU syntax. Diff that locale against the source message and fix the syntax there.

## Why it happens

ICU gives special meaning to apostrophes, braces, and the # sign. A translator typing a normal apostrophe accidentally opens a quoted section that never closes, and the parser reports the spot where the grammar stops making sense.

## Edge cases

- Smart quotes from word processors are not ICU quotes, normalize to straight quotes first
- The # sign outside a plural case is literal in some versions and an error in others, avoid it
- Argument names are case sensitive, count and Count are different arguments

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_fxBHwFmd-Au2bqNIvu0rGA
