Skip to main content

Guides

Fix “Invalid or Unexpected Token” in JavaScript

CleanPastedText editorial · Updated

Text workbench

Try it on your text

Cleaning mode

Removes hidden characters and standardizes AI-style punctuation.

Try a real example

Each sample contains a problem you cannot see.

Original

Pasted text

0 chars · 0 words

Cleaned

Ready to copy

0 changes

Text stays in this browser

Same words · No AI rewriting · No content logging

Why does JavaScript say “Invalid or unexpected token”?

Because the parser hit a code point it cannot use to start or continue any valid token at that exact position — not a keyword, not part of an identifier, not an operator, and not whitespace it recognizes. The code usually looks completely normal, because the character causing the failure has no visible glyph or looks identical to the one it replaced.

In a browser console the message is prefixed Uncaught: Uncaught SyntaxError: Invalid or unexpected token. In Node.js, the same underlying V8 parser prints the offending source line with a caret under the exact character, then SyntaxError: Invalid or unexpected token on its own line. Both come from the identical engine — Chrome and Node.js both run V8 — so the message text and the character's behavior are the same in either environment.

What the error looks like, verified character by character

The rows below come from actually running each snippet in Node.js 22.22.2 and in headless Chromium — not a forum post. Each line assigns a value next to the character in question:

CharacterTestResult in V8 (Node.js & Chromium)
Non-breaking space (U+00A0)const foo = 5;Runs. No error — treated as whitespace.
Zero-width space (U+200B), inside a const declarationconst foo = 5;SyntaxError: Missing initializer in const declaration
Zero-width space (U+200B), inside a plain assignmentx = 2;SyntaxError: Invalid or unexpected token
Curly quotes (U+201C / U+201D) in place of straight quotesconst s = “hello”;SyntaxError: Invalid or unexpected token

The two zero-width-space rows use the exact same character. Only the surrounding grammar changes which message V8 prints — a detail worth knowing before you trust the message text over the caret position.

Why doesn't a non-breaking space break JavaScript?

Because the ECMAScript specification puts it on the whitespace list by name. The White Space clause of ECMA-262 defines a <USP> category for "any code point in general category Space_Separator," with a note stating plainly: "U+0020 (SPACE) and U+00A0 (NO-BREAK SPACE) code points are part of <USP>." A non-breaking space is therefore valid ECMAScript whitespace everywhere a regular space is, which is exactly what the test above confirms.

That makes JavaScript the opposite of Python here. The guide to Python's invalid-character SyntaxError found that CPython rejects a non-breaking space outside a string with invalid non-printable character U+00A0. The same character, copied from the same PDF or the same chat interface, crashes one language and is silently accepted by the other — accepted, but still worth removing, since it still looks identical to a normal space to every human reading the file, and can trip up whitespace-sensitive diffs, linters, and string comparisons even without a parser error.

How is Firefox's error different from Chrome's or Node's?

Firefox's JavaScript engine, SpiderMonkey, takes a more direct approach: per MDN's "SyntaxError: illegal character" reference page, it names the exact code point in the message itself — SyntaxError: illegal character U+200B for a zero-width space, for example. V8 never does this: as the table above shows, Chrome and Node.js report either a generic Invalid or unexpected token or a context-dependent message that doesn't mention a character at all. If you can reproduce a paste-related syntax error in Firefox's console before debugging it in Chrome or Node, its message alone may already tell you which character to remove.

Can an invisible character break JavaScript without any error?

Yes — inside a string literal, template literal, or comment, the same characters that crash a bare expression are accepted without complaint, because that is exactly where the specification says whitespace and other code points are "considered significant code points forming part of a literal value." Tested directly:

> "hello\u200bworld".length
11
> "hello\u200bworld" === "helloworld"
false

No error, no warning — just a string one character longer than it looks, failing an equality check that should obviously pass. This is the case to actually worry about: a SyntaxError tells you exactly where to look, but a zero-width space sitting inside a string constant, an object key, or an API parameter changes behavior with zero diagnostic. It's the same class of problem covered in more depth by the guide to sanitizing copied text for code, JSON, and CSV.

How do I fix it, and stop it from recurring?

  1. Trust the caret, not the wording. As the const-declaration case shows, the message text can describe a completely different problem than "there's a hidden character here." The position under the caret is what actually points at the culprit.
  2. Check for curly quotes first if a string is involved. Code copied out of a chat interface, a slide deck, or a word processor frequently substitutes curly quotes for straight ones, which is the single most common cause of this error in copied code that otherwise looks correct.
  3. Run the file through a character-level cleaner if the error recurs on different lines — that pattern usually means the source you copied from keeps injecting the character rather than it being a one-off typo. Paste the snippet above and check the report: it lists every hidden character by name and code point before you copy the cleaned version back into your editor.
  4. Don't assume "no error" means "no problem." As shown above, the same characters are accepted silently inside strings. A clean pass through the invisible character remover catches those too, entirely in your browser, without altering indentation or any character you can actually see.

Common questions

Frequently asked questions

What does “Invalid or unexpected token” mean in JavaScript?

It means V8's parser (used by both Chrome and Node.js) reached a code point that cannot start or continue any valid token at that position — not a keyword, not an identifier character, not an operator, and not whitespace. In a browser console the message is prefixed Uncaught; in Node it appears under the offending source line with a caret. The most common real-world cause is a character that arrived through copy-paste rather than a typo, since it is usually invisible in the editor.

Does a non-breaking space (NBSP) break JavaScript code?

No. The ECMAScript specification's White Space table explicitly states that U+0020 (SPACE) and U+00A0 (NO-BREAK SPACE) are both part of the <USP> whitespace class, so a non-breaking space is spec-legal anywhere ordinary whitespace is allowed. Testing const foo\u00A0=\u00A05; directly in Node.js 22 and headless Chromium runs without error in both. This is the opposite of Python, whose tokenizer rejects a non-breaking space outside a string with SyntaxError: invalid non-printable character U+00A0.

Why did I get “Missing initializer in const declaration” instead of a message naming a character?

Because the same invisible character produces a different message depending on the surrounding grammar, not just its own properties. In testing, const foo\u200B = 5; (a zero-width space between an identifier and its declaration) produced SyntaxError: Missing initializer in const declaration in both Node.js 22 and headless Chromium, since the parser read the ZWSP as ending the identifier and then failed to find an = where one was required. The same character used in a plain assignment (x\u200B = 2;) instead produced the more generic SyntaxError: Invalid or unexpected token. The message text depends on context; the caret position under the character is the reliable clue in both cases.

How is Firefox's error message different from Chrome's or Node's?

Firefox's SpiderMonkey engine reports these as SyntaxError: illegal character U+200B, naming the exact code point directly in the message, per MDN's “SyntaxError: illegal character” reference page. V8 (Chrome and Node.js) does not name the character in its message text at all — it reports a generic Invalid or unexpected token or a context-dependent message like the const case above, and only the caret position tells you where to look. If you can reproduce the error in Firefox's console, its message is the faster way to identify which character is at fault.

Can an invisible character break JavaScript without causing any error?

Yes, and it is more dangerous than a crash because nothing alerts you. Inside a string literal, JavaScript accepts a zero-width space exactly like any other character: "hello\u200bworld".length returns 11, not 10, and "hello\u200bworld" === "helloworld" returns false, both confirmed by direct testing, with no error or warning at either point. That is how invisible characters cause failed string comparisons, broken object keys, or mismatched API parameters instead of a SyntaxError — the same silent-failure pattern covered in the guide to sanitizing copied text for code, JSON, and CSV.

How do I stop this from happening when I copy code from ChatGPT or Claude?

Paste the snippet through a character-level cleaner before saving it, rather than retyping the line by hand to find one invisible character. Chat interfaces render code blocks as HTML, and that HTML-to-clipboard path is exactly where zero-width spaces and curly quotes get introduced in place of plain ASCII — see how hidden characters end up in ChatGPT output for the underlying mechanism. A cleaning preset that removes invisible characters and normalizes typography fixes both causes in the FAQ above in one pass, without touching indentation or any visible character.

Continue reading

Related guides & tools