Migrate to v10.x
ESLint v10.0.0 is a major release of ESLint, and as such, has several breaking changes that you need to be aware of. This guide is intended to walk you through the breaking changes.
The lists below are ordered roughly by the number of users each change is expected to affect, where the first items are expected to affect the most users.
Table of Contents
Breaking changes for users
- Node.js < v20.19, v21, v23 are no longer supported
- New configuration file lookup algorithm
- Deprecated options of the
radixrule no-shadow-restricted-namesnow reportsglobalThisby defaulteslint:recommendedhas been updated- Jiti < v2.2.0 are no longer supported
eslint-envcomments are reported as errorsfunc-namesschema is stricterallowConstructorFlagsoption ofno-invalid-regexpnow accepts only unique items
Breaking changes for plugin developers
- Node.js < v20.19, v21, v23 are no longer supported
- Removal of
typeproperty in errors of invalidRuleTestercases - Fixer methods now require string
textarguments ProgramAST node range spans entire source text
Breaking changes for integration developers
- Node.js < v20.19, v21, v23 are no longer supported
- New configuration file lookup algorithm
- Removal of
nodeTypeproperty inLintMessageobjects ProgramAST node range spans entire source text
Node.js < v20.19, v21, v23 are no longer supported
ESLint is officially dropping support for these versions of Node.js starting with ESLint v10.0.0. ESLint now supports the following versions of Node.js:
- Node.js v20.19.0 and above
- Node.js v22.13.0 and above
- Node.js v24 and above
To address: Make sure you upgrade to at least Node.js v20.19.0 when using ESLint v10. One important thing to double check is the Node.js version supported by your editor when using ESLint via editor integrations. If you are unable to upgrade, we recommend continuing to use ESLint v9 until you are able to upgrade Node.js.
Related issue(s): #19969
New configuration file lookup algorithm
In ESLint v9, the alternate config lookup behavior could be enabled with the v10_config_lookup_from_file feature flag. This behavior made ESLint locate eslint.config.* by starting from the directory of each linted file and searching up towards the filesystem root. In ESLint v10, this behavior is now the default and the v10_config_lookup_from_file flag has been removed. Attempting to use this flag will now result in an error.
To address:
- Remove any usage of the flag in your setup:
- CLI: remove
--flag v10_config_lookup_from_file. - Environment: remove
v10_config_lookup_from_filefromESLINT_FLAGS. - API: remove
"v10_config_lookup_from_file"from theflagsarray passed tonew ESLint()ornew Linter().
- CLI: remove
- If you relied on the previous (cwd-based) lookup behavior, provide an explicit config path with
--config path/to/eslint.config.js.
Related issue(s): #19967
Deprecated options of the radix rule
As of ESLint v10.0.0, string options "always" and "as-needed" of the radix rule are deprecated. Setting either of these options doesn’t change the behavior of this rule, which now always enforces providing a radix, as it was the case when the "always" option (default) was specified. Since the default radix depends on the first argument of parseInt(), this rule assumes that the second argument (the radix) is always needed.
The default behavior of this rule has not been changed.
To address:
- If you are using this rule without any options specified, there is no action required.
- If you are using this rule with the
"always"option explicitly specified, remove the option. The behavior of this rule will remain the same. - If you are using this rule with the
"as-needed"option, remove the option and update your code to always provide the second argument to theparseInt()function. Alternatively, you can disable this rule.
Related issue(s): #19916
no-shadow-restricted-names now reports globalThis by default
In ESLint v10, the no-shadow-restricted-names rule now treats globalThis as a restricted name by default. Consequently, the reportGlobalThis option now defaults to true (previously false). As a result, declarations such as const globalThis = "foo"; or function globalThis() {} will now be reported by default.
To address:
- Rename local identifiers named
globalThisto avoid shadowing the global. - Or restore the previous behavior by configuring the rule explicitly:
{
"rules": {
"no-shadow-restricted-names": ["error", { "reportGlobalThis": false }]
}
}
Related issue(s): #19673
eslint:recommended has been updated
Three new rules have been enabled in eslint:recommended:
To address: Fix errors or disable these rules.
Related issue(s): #19966
Jiti < v2.2.0 are no longer supported
ESLint is officially dropping support for versions of jiti that are less than v2.2.0.
To address: If you’ve authored your config file in TypeScript and have jiti v2.1.2 or earlier installed, be sure to update it to at least 2.2.0 when using ESLint v10.
Related issue(s): #19765
Removal of type property in errors of invalid RuleTester cases
In ESLint v10, the deprecated type property in errors of invalid test cases for rules has been removed. Using the type property in test cases now throws an error.
To address: Remove the type property from error objects in invalid test cases.
Related issue(s): #19029
Fixer methods now require string text arguments
In ESLint v10, all rule fixer methods that accept a text argument now require that it be a string. Providing a non-string value will throw a TypeError.
Affected methods:
insertTextBefore(nodeOrToken, text)insertTextBeforeRange(range, text)insertTextAfter(nodeOrToken, text)insertTextAfterRange(range, text)replaceText(nodeOrToken, text)replaceTextRange(range, text)
To address: Ensure the text value you pass to fixer methods is a string.
Related issue(s): #18807
Removal of nodeType property in LintMessage objects
In ESLint v10, the deprecated nodeType property on LintMessage objects has been removed. This affects consumers of the Node.js API (for example, custom formatters and editor/tool integrations) that previously relied on message.nodeType.
To address: Remove all usages of message.nodeType in your integrations and formatters.
Related issue(s): #19029
Program AST node range spans entire source text
ESLint v10 changes how the Program AST node’s range is calculated: it now spans the entire source text, including any leading and trailing comments and whitespace.
Previously, the Program node’s range excluded leading and trailing comments/whitespace, which could be unintuitive. For example:
// Leading comment
const x = 1;
// Trailing comment
In ESLint v9 and earlier, Program.range covers only const x = 1; (excludes surrounding comments/whitespace).
Starting with ESLint v10, Program.range covers the entire source text, including the leading and trailing comments/whitespace.
To address:
- For rule and plugin authors: If your code depends on the previous
Program.rangebehavior, or onSourceCodemethods that assume it (such assourceCode.getCommentsBefore(programNode)to retrieve all leading comments), update your logic. - For custom parsers: Set
Program.rangeto cover the full source text (typically[0, code.length]).
Related issue(s): eslint/js#648
eslint-env comments are reported as errors
In the now obsolete ESLint v8 configuration system, /* eslint-env */ comments could be used to define globals for a file. The current configuration system does not support such comments, and starting with ESLint v10, they are reported as errors during linting.
error: /* eslint-env */ comments are no longer supported at file.js:1:1:
> 1 | /* eslint-env node -- Used in Node.js */
| ^
To address: Remove any eslint-env comments from your code. If you are still using the old configuration system and need help migrating, check the migration guide.
Related issue(s): #13481
func-names schema is stricter
In ESLint v10, the func-names rule schema now disallows extra items in the options array. Previously, configurations that included additional array elements beyond the allowed options were accepted but ignored. Such configurations are now considered invalid.
For example, this configuration is now invalid due to the extra element "foo":
/*eslint func-names: ["error", "always", { "generators": "never" }, "foo"]*/
To address:
- Remove any extra array elements from your
func-namesconfiguration so that it contains only:- a base string option:
"always" | "as-needed" | "never", and - optionally, an object option:
{ "generators": "always" | "as-needed" | "never" }.
- a base string option:
Related issue(s): #20134
allowConstructorFlags option of no-invalid-regexp now accepts only unique items
In ESLint v10, the allowConstructorFlags option of no-invalid-regexp no longer accepts duplicate flags as input. Previously, configurations with duplicate flags in the array were accepted but treated the same as having unique flags. Such configurations are now considered invalid and will result in a configuration error.
For example, this configuration is now invalid due to the duplicate "u" flag:
/*eslint no-invalid-regexp: ["error", { "allowConstructorFlags": ["u", "y", "u"] }]*/
To address: Remove any duplicate flags from your allowConstructorFlags array configuration of no-invalid-regexp rule. Each flag should appear only once in the array.
Related issue(s): #18755