How to Fix ESLint Parsing Error: Unexpected Token
On this page
You're writing perfectly valid JavaScript or TypeScript, your app runs fine, but ESLint throws Parsing Error: Unexpected Token and lights up your editor like a Christmas tree. This is one of the most common — and most frustrating — ESLint errors because the problem is almost never your code. It's your ESLint configuration.
Let's walk through every cause of this error and how to fix each one.
TL;DR
The Parsing Error: Unexpected Token error means ESLint's parser doesn't understand your code's syntax. The most common fixes are: (1) install and configure @typescript-eslint/parser for TypeScript projects, (2) set the correct ecmaVersion and sourceType in your ESLint config, or (3) add the JSX plugin if you're using React. The fix usually takes under two minutes once you know the cause.
What Causes the ESLint Parsing Error?
ESLint uses a parser to read your code before it can lint it. The default parser only understands standard ECMAScript. When your code uses syntax the parser doesn't recognize — TypeScript types, JSX, optional chaining in older configs, decorators — it throws a parsing error. The error isn't saying your code is wrong. It's saying ESLint can't read it.
There are five main causes:
- Using TypeScript without
@typescript-eslint/parser - Wrong
ecmaVersionsetting for modern JavaScript features - Missing JSX/React configuration
- Mismatched ESLint and parser versions
- ESLint trying to lint non-JavaScript files
Let's fix each one.
Fix 1: Configure the TypeScript Parser
This is the number one cause. You're writing TypeScript, but ESLint is still using its default parser, which has zero understanding of type annotations, interfaces, or enums.
The error usually looks like this:
Parsing error: Unexpected token
1 | interface User {
| ^
2 | name: string;
3 | }
Install the TypeScript parser and plugin:
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
Then update your ESLint config. If you're using the flat config format (ESLint 9+, which is the default in 2026):
// eslint.config.js
import tseslint from '@typescript-eslint/eslint-plugin';
import tsparser from '@typescript-eslint/parser';
export default [
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: tsparser,
parserOptions: {
project: './tsconfig.json',
},
},
plugins: {
'@typescript-eslint': tseslint,
},
rules: {
...tseslint.configs.recommended.rules,
},
},
];
If you're still on the legacy .eslintrc format:
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": ["plugin:@typescript-eslint/recommended"]
}
After updating your config, restart your editor. VS Code, in particular, caches the ESLint config aggressively. If you're using VS Code with the ESLint extension, open the command palette and run ESLint: Restart ESLint Server.
Fix 2: Set the Correct ecmaVersion
If you're using modern JavaScript features like optional chaining (?.), nullish coalescing (??), top-level await, or class fields, and ESLint is complaining, your ecmaVersion is too low.
// eslint.config.js
export default [
{
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
},
];
For legacy configs:
{
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
}
}
Setting ecmaVersion to "latest" tells ESLint to support the most recent finalized ECMAScript standard. There's rarely a reason to pin this to a specific year unless you're intentionally restricting language features.
Also make sure sourceType is set to "module" if you're using import/export statements. If it's set to "script" (the default in legacy configs), ESLint will choke on any ES module syntax.
Fix 3: Enable JSX Parsing
React developers hit this error when ESLint doesn't know how to handle JSX. The error typically points to the opening angle bracket:
Parsing error: Unexpected token
5 | function App() {
6 | return (
> 7 | <div>
| ^
8 | <h1>Hello</h1>
For flat config:
// eslint.config.js
export default [
{
files: ['**/*.jsx', '**/*.tsx'],
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
},
];
If you're using TypeScript with React, the TypeScript parser handles JSX automatically when you set it up as shown in Fix 1 — just make sure your tsconfig.json has "jsx": "react-jsx" or "jsx": "preserve" set.
This same type of parsing mismatch is a common root cause behind Next.js hydration errors too — where the build toolchain and the runtime disagree on how to interpret your component syntax.
Fix 4: Fix Version Mismatches
ESLint 9 introduced flat config as the default and deprecated the legacy config format. If you've upgraded ESLint but your parser or plugins are outdated, you'll get parsing errors. The reverse is also true — a new parser version might not work with an old ESLint.
Check your current versions:
npx eslint --version
npm list @typescript-eslint/parser @typescript-eslint/eslint-plugin
As of mid-2026, here are the compatible version ranges:
- ESLint 9.x: Use
@typescript-eslint/parserv8+ and flat config - ESLint 8.x: Use
@typescript-eslint/parserv6 or v7 with.eslintrc
If versions are mismatched, update everything together:
npm install --save-dev eslint@latest @typescript-eslint/parser@latest @typescript-eslint/eslint-plugin@latest
After updating, delete node_modules and reinstall to clear any cached resolution issues:
rm -rf node_modules package-lock.json
npm install
Fix 5: Exclude Non-JavaScript Files
ESLint will try to parse every file it encounters unless you tell it not to. If it hits a .json, .css, .svg, or .md file, you'll get a parsing error.
In flat config, use ignores:
// eslint.config.js
export default [
{
ignores: [
'node_modules/**',
'dist/**',
'build/**',
'**/*.json',
'**/*.css',
'**/*.svg',
],
},
// ... your other config objects
];
For legacy configs, use .eslintignore or the ignorePatterns field in your config.
A common gotcha: if you have a monorepo or a Docker-based development setup, ESLint might pick up generated files or build artifacts that contain invalid syntax. Always check your ignore patterns when working in complex project structures.
Debugging Tip: Find the Exact Problem
When the error message isn't clear enough, run ESLint with the --debug flag:
npx eslint --debug src/App.tsx 2>&1 | head -50
This tells you exactly which parser ESLint is using, which config file it loaded, and where parsing failed. Nine times out of ten, you'll see it's using the default espree parser instead of the TypeScript parser — meaning your config isn't being picked up correctly.
You can also verify which config ESLint resolves for a specific file:
npx eslint --print-config src/App.tsx
This outputs the fully merged configuration, including the parser, plugins, and all rules. If parser shows espree or is missing, that's your problem.
Common Pitfall: Multiple Config Files
ESLint uses a config cascade. If you have both eslint.config.js (flat config) and .eslintrc.json (legacy) in your project, ESLint 9+ will only read the flat config and silently ignore the legacy one. If your parser is configured in the legacy file, it won't be applied.
Pick one format and delete the other. If you're starting fresh or upgrading, go with flat config — it's the future and honestly more straightforward once you get used to it.
When It's Actually a Syntax Error
About 5% of the time, the parsing error is genuinely pointing at a syntax error in your code. Before diving into config changes, do a quick sanity check:
npx tsc --noEmit
If TypeScript itself can't compile the file, the problem is your code, not ESLint. Fix the syntax error first.
Quick Reference: Config Templates
Here's a battle-tested flat config for a TypeScript + React project that eliminates most parsing errors:
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
{
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parserOptions: {
ecmaFeatures: { jsx: true },
},
},
},
{
ignores: ['node_modules/**', 'dist/**', 'build/**'],
}
);
This single config handles TypeScript, JSX, modern ECMAScript features, and common ignore patterns. If you're maintaining multiple projects or working with a team at an agency building client projects, having a shared base config like this saves hours of debugging.
For teams that rely on AI code assistants to generate code, keeping your ESLint config correct is doubly important — AI-generated code often uses the latest syntax features, and a misconfigured linter will flag perfectly valid suggestions as errors.
Wrapping Up
The Parsing Error: Unexpected Token error is always a config problem, not a code problem (well, 95% of the time). The fix follows a simple checklist:
- Are you using TypeScript? Install and configure
@typescript-eslint/parser. - Are you using modern JS syntax? Set
ecmaVersion: "latest". - Are you using JSX? Enable
ecmaFeatures.jsx. - Are your package versions compatible? Update everything together.
- Is ESLint parsing files it shouldn't? Set up proper ignore patterns.
Run through those five checks and you'll resolve the error in under two minutes every time.
Sources
Related Articles
How to Debug Node.js Memory Leaks (Step-by-Step Guide)
Learn how to detect, diagnose, and fix Node.js memory leaks using heap snapshots, Chrome DevTools, and clinic.js — with real code examples.
How to Set Up GitHub Actions for CI/CD (Beginner-Friendly Guide)
Learn how to set up GitHub Actions for CI/CD pipelines — from your first workflow file to automated deployments with real YAML examples.
Running Local LLMs With Ollama: Developer Setup Guide
Set up Ollama to run local LLMs on your machine. Covers installation, model selection, API usage, and integrating local models into your dev workflow.