lenec ru

← все посты

npm ERR! ERESOLVE unable to resolve dependency tree — что делать

13K

Ошибка ERESOLVE unable to resolve dependency tree вылезает после npm install и обычно означает, что npm не может уложить версии пакетов так, чтобы все peer-зависимости совпали. Раньше npm в таких случаях молча ставил что было, начиная с npm 7 — отказывается ставить и кидает ошибку.

Я обычно сталкиваюсь с этой ошибкой при апгрейдах React или Next, реже — при добавлении старых UI-китов. Покажу, как читать сообщение и какие варианты починки нормальные, а какие — самострел.

Как читать вывод

Типичный вывод выглядит так:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: my-app@0.1.0
npm ERR! Found: react@19.0.0
npm ERR! node_modules/react
npm ERR!   react@"19.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^17.0.0 || ^18.0.0" from react-some-lib@2.3.0
npm ERR! node_modules/react-some-lib
npm ERR!   react-some-lib@"2.3.0" from the root project

Здесь читается так:

  • в проекте уже стоит react@19.0.0;
  • пакет react-some-lib@2.3.0 в peer-зависимостях ждёт react@^17 || ^18;
  • npm не понимает, как это совместить, и ругается.

Дальше — выбор: подобрать версию пакета, которая поддерживает React 19, или принудительно сказать npm «я знаю, что делаю».

Правильный путь: посмотреть, поддерживает ли пакет нужную версию

Прежде чем тыкать --force, иду в npm и смотрю свежие версии пакета. Часто бывает так:

  • v2.3.0 поддерживает React 17–18;
  • v3.0.0 (или beta) уже работает с React 19.

Если новая версия есть — обновляю:

npm install react-some-lib@latest

В большинстве случаев на этом всё заканчивается. Особенно после крупных мажоров React, когда у мейнтейнеров просто была пара недель на обновление peer-диапазонов.

Когда обновлений нет

Бывает, что пакет давно не обновляли. Тогда вариантов три, и я выбираю их в таком порядке:

1. Заменить пакет на живой аналог

Особенно актуально для UI-библиотек. Если автор пропал — тащить его наследие лет на пять вперёд проще не стоит.

2. --legacy-peer-deps

Это поведение npm 6: устанавливай, peer-несовпадения считай предупреждением, не ошибкой.

npm install --legacy-peer-deps

Чтобы не вспоминать каждый раз, можно зафиксировать в .npmrc у проекта:

echo 'legacy-peer-deps=true' >> .npmrc

Минус: ты явно говоришь npm «закрывай глаза на конфликты». Если пакет внутри ждёт API-методов из своей версии React, а у тебя другая — может рантайм-уронить.

3. overrides в package.json

Самый аккуратный способ — точечно зафиксировать версию проблемной зависимости через overrides. Подходит, когда сторонний пакет тащит зависимость, которую тебе хочется ровно ту же, что и у тебя в корне.

{
  "overrides": {
    "react": "19.0.0",
    "react-some-lib": {
      "react": "19.0.0"
    }
  }
}

Дальше — npm install. Этот способ лучше --legacy-peer-deps, потому что ты явно фиксируешь решение, а не глобально отключаешь проверку.

Чего я никогда не делаю

--force. Эта опция говорит npm «делай как хочешь», и часто оставляет lockfile в странном состоянии. Симптомы — гуляющие версии, баги, которые воспроизводятся только у одного человека из команды. Если уж нужно ослабить проверку, я выбираю --legacy-peer-deps: он хотя бы предсказуемо ведёт себя только с peer-зависимостями.

И не удаляю package-lock.json «чтобы решилось». Удаление лока в попытке починить ERESOLVE обычно ничего не лечит, потому что ошибка — про peer-диапазоны в самих пакетах, а не про лок.

Особый случай: монорепо и workspaces

В монорепе ERESOLVE может прилететь, потому что один из workspace-пакетов фиксирует одну версию зависимости, а другой — другую. Здесь стандартный путь:

  • привести версии к общему знаменателю в package.json каждого пакета;
  • или использовать resolutions (Yarn) / overrides (npm) на уровне корня.

В моей последней монорепе с pnpm я обычно ставлю strict-peer-dependencies=false на этапе разработки, а в CI прогоняю pnpm install --frozen-lockfile — так на миграциях вижу проблемы рано, а не на бою.

Чек-лист, который у меня всегда под рукой

  • Прочитал стек ошибки, понял какой пакет конфликтует.
  • Проверил последнюю версию пакета — может, уже починили.
  • Если пакет жив — обновил.
  • Если нет — заменил на живой или прописал overrides.
  • --legacy-peer-deps — только если уверен, что это безопасно.
  • --force — никогда.

Если правильно прочитать сообщение, ERESOLVE даже полезен: он не даёт собрать заведомо несовместимый набор пакетов. Без него такие штуки всплывают через две недели на проде в виде «у нас опять упал чекаут».

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.