Versions

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

Breaking changes for plugin developers

Breaking changes for integration developers


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_file from ESLINT_FLAGS.
    • API: remove "v10_config_lookup_from_file" from the flags array passed to new ESLint() or new Linter().
  • 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 the parseInt() 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 globalThis to 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.range behavior, or on SourceCode methods that assume it (such as sourceCode.getCommentsBefore(programNode) to retrieve all leading comments), update your logic.
  • For custom parsers: Set Program.range to 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-names configuration so that it contains only:
    • a base string option: "always" | "as-needed" | "never", and
    • optionally, an object option: { "generators": "always" | "as-needed" | "never" }.

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

Change Language