
ESLint v9 reaches end-of-life on August 6 — five days from today. After that date, the v9 branch gets no security patches and no bug fixes. The migration to v10 is not complicated, but one silent gotcha in CI will catch teams that skip the checklist: the Node.js minimum version jumped, and most CI configs do not specify a precise enough version to catch it before it breaks.
What Changes in ESLint v10
ESLint v10 shipped in February 2026 and has been at v10.8.0 since July. The breaking changes fall into three categories worth understanding before you type a single command.
1. The eslintrc Format Is Gone
This one has been coming since v9. In v10, it is final: .eslintrc.json, .eslintrc.js, .eslintrc.yml — none of them work. The ESLINT_USE_FLAT_CONFIG=false environment variable no longer has any effect. Flat config (eslint.config.js) is now the only supported format, full stop.
If you already migrated to flat config during the v9 window, you are done with this part. If you have not, the codemod handles most of it automatically.
2. Node.js v18 and Early v20 Are Dropped
ESLint v10 requires ^20.19.0 || ^22.13.0 || >=24. Node 18 is completely out. Node 20.0 through 20.18 are out. Most developers running Node 22 LTS are fine, but CI pipelines are a different story. A pipeline that specifies node:20 without a patch version may pull a build image that fails silently — ESLint installs, runs, and errors on the Node version check before linting a single file.
This is the change most likely to surprise teams. The config looks right. The install succeeds. The first lint run fails with a Node version error instead of a lint error, which is confusing if you are not expecting it.
3. /* eslint-env */ Comments Are Now Lint Errors
Any file containing /* eslint-env browser */ or /* eslint-env node */ will now produce a lint error on those comments. These were deprecated in v9 and removed in v10. A codebase with years of history likely has dozens of them. Running a grep before the migration tells you exactly what you are dealing with:
grep -r "eslint-env" src/ --include="*.js" --include="*.ts"
The replacement is a globals entry in your flat config — more explicit, no magic.
How to Migrate: Four Steps
Step 1: Check Your Versions
npx eslint --version
node --version
Confirm you are on v9.x and that Node is at least 20.19.0. If Node is below that, update your local environment and CI config before touching ESLint.
Step 2: Run the Migration Codemod
If you are still on .eslintrc.json or similar, the official codemod converts it to flat config format:
npx @eslint/migrate-config .eslintrc.json
This produces an eslint.config.mjs file. Review it before committing — particularly the plugins section, where string-based plugin names become direct imports. If your .eslintrc.js contains conditional logic, the codemod only captures the evaluated output, so that logic needs manual rewriting.
Step 3: Upgrade ESLint and Dependencies
npm install --save-dev eslint@latest
If you use typescript-eslint, upgrade that as well — v8 or later is required for ESLint v10 compatibility. Then run your linter and see what surfaces.
Step 4: Remove Lingering eslint-env Comments
Use the grep from Step 1 to find remaining /* eslint-env */ comments. Replace them with a languageOptions.globals entry in eslint.config.mjs:
import globals from "globals";
export default [
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
},
},
];
Run the linter again. Most projects land here in under an hour.
One More Monorepo Note
ESLint v10 now finds its config file starting from the directory of each linted file, rather than from the current working directory. For monorepos, this is an improvement — each package can have its own eslint.config.js and ESLint finds it automatically. But if you run ESLint from a root script and depend on a single root config applying everywhere, verify that config path resolution still works as expected by running a test lint across all packages.
The Upside of Getting This Done
Flat config deserves more credit than the migration friction suggests. No more silent rule inheritance from parent directories. No more YAML with escape character edge cases. No more wondering which config file wins in a cascading setup. The eslint.config.js file is a plain JavaScript module — you import, compose, and export configs the same way you do everything else in your project.
ESLint v10.8.0 is the current release, and the team is shipping minor updates monthly. The language plugin system covering CSS and Markdown is expanding. ESLint is actively investing in v10 — and that investment only shows up once you are on it.
The deadline is August 6. The migration takes an afternoon. Run the codemod, fix the Node version in CI, grep for eslint-env comments, and ship it. The official migration guide covers every edge case if you hit something unusual.













