# Known issue: `@eslint/js` resolves to an ESLint 10 build on ESLint 9

This config declares `@eslint/js` as `^9.38.0 || ^10.0.0`, matching its own `eslint` range. A resolver takes
the highest version a range allows, so on a project running ESLint 9 it selects `@eslint/js@10.0.1`, whose
own peer is `eslint@^10.0.0`. Under npm the install fails outright:

```text
npm error While resolving: @eslint/js@10.0.1
npm error Found: eslint@9.38.0
npm error   peer eslint@"^9.38.0 || ^10.0.0" from @bitfactory/eslint-config
npm error Could not resolve dependency:
npm error   peer @eslint/js@"^9.38.0 || ^10.0.0" from @bitfactory/eslint-config
npm error Conflicting peer dependency: eslint@10.8.1
```

The resolution npm proposes is to install `eslint@10.8.1`, which is an ESLint 10 upgrade rather than a fix.
`@eslint/js` is a required peer of this package, not an optional one, so there is no version of this that
degrades to a warning you can ignore. `pnpm` with `strict-peer-dependencies` fails for the same reason.

## Whether this affects you

You are affected if **both** apply:

- You run ESLint 9 (`^9.38.0`). ESLint 10 projects resolve `@eslint/js@10.0.1` and its peer is satisfied.
- You let `@eslint/js` resolve by range instead of pinning it.

## Remedy

Pin `@eslint/js` to the major you actually run. On ESLint 9:

```jsonc
{
  "devDependencies": {
    "@eslint/js": "9.38.0"
  }
}
```

Any `9.x` at or above `9.38.0` works; the declared range starts there, so an earlier `9.x` fails the peer
check for a different reason. `9.38.0` and `10.0.0` are the two versions in that range that publish no
`eslint` peer at all, so neither can conflict with whichever ESLint you run.

If a transitive dependency reintroduces the range, force it:

```jsonc
// npm and yarn
{ "overrides": { "@eslint/js": "9.38.0" } }

// pnpm
{ "pnpm": { "overrides": { "@eslint/js": "9.38.0" } } }
```

## Why the range is not simply narrowed

The constraint this needs is "match the installed `eslint` major", which a semver range cannot express.
Capping at `<10.0.1` would be this package narrowing what it accepts, a breaking change, and would go stale
the next time `@eslint/js` publishes a patch. Marking the peer optional would replace a clear install error
with a module-resolution crash when the config loads, because `index.js` imports `@eslint/js`
unconditionally. ADR-0012 records the decision and the alternatives in full.

Dropping ESLint 9 support removes the spanning range and dissolves this issue; that is tracked separately.
