npm install зависает или падает по таймауту: чек-лист

, 6 мин чтения

Зависший npm install выглядит одинаково, а причины разные: реестр, DNS, IPv6, прокси, повреждённый кэш. Идите по списку сверху вниз и не меняйте всё сразу, иначе не поймёте, что помогло.

Что означают ошибки

В новых версиях npm строки ошибок начинаются с npm error, в старых с npm ERR!. Коды при этом те же.

КодПричина
ETIMEDOUTСоединение с реестром не установилось за отведённое время. Сеть, прокси или межсетевой экран
ECONNRESETСоединение оборвали посреди передачи. Нестабильный канал или прокси, который рвёт долгие запросы
ERR_SOCKET_TIMEOUTСоединение есть, но данные перестали приходить
EAI_AGAINВременный сбой DNS: имя реестра не разрешилось
ENOTFOUNDDNS не знает такого имени. Часто это опечатка в адресе реестра в .npmrc
SELF_SIGNED_CERT_IN_CHAIN, UNABLE_TO_GET_ISSUER_CERT_LOCALLYКорпоративный прокси подменяет сертификаты
EINTEGRITYКонтрольная сумма пакета не совпала: повреждённый кэш или lockfile
E401, E403 или E404 на пакете компанииПакет ищется не в том реестре или нет токена. Проверьте строку @scope:registry в .npmrc

Типичное сообщение о таймауте выглядит так:

npm error code ETIMEDOUT
npm error network request to https://registry.npmjs.org/express failed, reason: connect ETIMEDOUT 104.16.x.x:443
npm error network This is a problem related to network connectivity.

Последняя строка лишь подтверждает, что проблема в сети, а не в вашем package.json. Полезнее адрес в середине: он показывает, куда npm пытался подключиться. Если там не ваш реестр или прокси, ищите лишнюю настройку в .npmrc.

Посмотрите, на чём застряло

Запустите установку с подробным логом: npm install --loglevel=http. Видно, какой пакет и откуда скачивается. Если строка прогресса долго стоит на idealTree, npm ещё собирает дерево зависимостей и ждёт метаданные из реестра. Если на reify, идёт скачивание и распаковка.

Бывает, что установка зависает на одном и том же пакете уже после загрузки. Это не реестр: скрипт postinstall пакета качает бинарник с другого сервера. Так делают, например, Puppeteer со своим браузером и Electron со своей сборкой. Проверьте запуском npm install --ignore-scripts: если так всё проходит быстро, тормозит скрипт. У таких пакетов обычно есть переменные окружения для зеркала или пропуска загрузки, например PUPPETEER_SKIP_DOWNLOAD и ELECTRON_MIRROR, подробности в их документации.

Полный лог каждого запуска лежит в ~/.npm/_logs/, на Windows в %LocalAppData%\npm-cache\_logs. Быстрые проверки связи с реестром:

npm config get registry
npm ping
npm view react version
npm doctor

npm ping проверяет, что реестр отвечает, npm view запрашивает метаданные пакета, как это делает установка, а npm doctor дополнительно смотрит права на кэш и версии Node.js и npm. Для публичных пакетов реестр должен быть https://registry.npmjs.org/, если в компании не используется свой прокси-реестр. Команда npm config list покажет, из каких файлов .npmrc пришли настройки. Частая находка: забытый .npmrc в проекте или в домашнем каталоге с адресом старого корпоративного реестра.

Таймауты и повторы

npm config set fetch-retries 5
npm config set fetch-retry-mintimeout 20000
npm config set fetch-retry-maxtimeout 120000

По умолчанию npm делает две повторные попытки, а пауза между ними растёт от 10 секунд до минуты. С этими значениями он повторит неудачный запрос пять раз и будет ждать между попытками дольше. Общий таймаут запроса fetch-timeout по умолчанию равен пяти минутам. Уменьшать его стоит, только если вы хотите, чтобы зависшая установка падала быстрее.

На нестабильном канале помогает и меньшее число одновременных соединений: npm config set maxsockets 5, по умолчанию их 15. Флаг --no-audit убирает лишний запрос к сервису аудита при каждой установке.

Команда npm config set пишет в пользовательский ~/.npmrc. Чтобы настройки действовали для всего проекта и в CI, положите те же строки в .npmrc в корне репозитория, например fetch-retries=5.

Проблемы с IPv6 и DNS

Начиная с Node.js 17 адреса используются в том порядке, в котором их вернул DNS. Если IPv6-маршрут у провайдера работает плохо, соединение висит до таймаута. Попросите Node.js сначала пробовать IPv4:

export NODE_OPTIONS=--dns-result-order=ipv4first

В PowerShell то же самое: $env:NODE_OPTIONS="--dns-result-order=ipv4first". В свежих версиях Node.js есть автоматический перебор адресов (autoSelectFamily), поэтому проблема встречается реже, но флаг остаётся быстрым способом её исключить.

Убедиться, что дело в IPv6, можно без npm: сравните curl -4 -sI https://registry.npmjs.org/ и curl -6 -sI https://registry.npmjs.org/. Если второй вариант зависает, а первый отвечает сразу, флаг выше решит проблему.

DNS проверьте отдельно: nslookup registry.npmjs.org. Если имя разрешается долго или через раз, меняйте DNS-сервер в системе, а не настройки npm.

Прокси и корпоративные сертификаты

Если в сети интернет доступен только через прокси, укажите его явно:

npm config set proxy http://proxy.example.com:3128
npm config set https-proxy http://proxy.example.com:3128

npm также читает переменные HTTPS_PROXY и NO_PROXY. Внутренний реестр компании добавьте в noproxy, чтобы запросы к нему не уходили через внешний прокси. И наоборот: если прокси больше нет, а в .npmrc остались эти строки, установка будет висеть до таймаута.

Когда прокси подменяет сертификаты, не отключайте проверку через strict-ssl false: так npm примет любой поддельный сертификат. Правильный путь: получить корневой сертификат компании и указать его в cafile или в переменной NODE_EXTRA_CA_CERTS.

npm config set cafile /path/to/corp-ca.pem
export NODE_EXTRA_CA_CERTS=/path/to/corp-ca.pem

Кэш и lockfile

  • Для чистой установки по lockfile используйте npm ci: она быстрее и повторяемее, чем npm install, и сразу падает, если package.json и package-lock.json расходятся.
  • npm cache verify проверит и починит локальный кэш. После ошибки EINTEGRITY начните с неё, крайний вариант npm cache clean --force.
  • Флаг --prefer-offline берёт пакеты из кэша без проверки свежести и ходит в сеть только за недостающими.
  • В CI кэшируйте каталог ~/.npm, а не node_modules: npm ci всё равно удаляет node_modules перед установкой. В GitHub Actions это делает actions/setup-node с параметром cache: npm.
  • Если вы сменили registry, lockfile переписывать не нужно: npm сам подставляет ваш реестр вместо registry.npmjs.org (настройка replace-registry-host).

Особенности Windows, WSL и macOS

  • Windows: распаковку тысяч мелких файлов заметно замедляет антивирусная проверка. Если проект лежит в синхронизируемой папке вроде OneDrive, установка идёт ещё медленнее и иногда падает с EPERM или EBUSY, когда другой процесс держит файл открытым.
  • WSL 2: держите проект в файловой системе Linux, например в ~/project, а не в /mnt/c/. Доступ к дискам Windows из WSL заметно медленнее, и на тысячах файлов node_modules это хорошо видно.
  • macOS и Linux: если глобальные пакеты ставились через sudo, в кэше могли остаться файлы root, и следующие установки падают с EACCES. Документация npm советует ставить Node.js через менеджер версий, например nvm, тогда sudo не нужен.
  • Docker: смонтируйте кэш BuildKit (--mount=type=cache,target=/root/.npm), иначе каждая сборка образа скачивает все пакеты заново.
  • Если установка медленная даже из кэша и без сети, дело в диске или антивирусе, а не в реестре.

pnpm, Yarn и pip

pnpm читает те же ключи fetch-retries и fetch-timeout из .npmrc. В Yarn 1 таймаут задаётся флагом yarn install --network-timeout 600000, в Yarn 2 и новее параметрами httpTimeout и httpRetry в .yarnrc.yml. Для Python аналог такой:

pip install --timeout 60 --retries 5 -r requirements.txt
pip config set global.timeout 60

По умолчанию pip ждёт ответа 15 секунд, на медленном канале этого мало.

Если всё настроено, а пакеты не качаются

Когда даже с повторами и таймаутами загрузка обрывается, проблема в сети по пути до реестра. Попробуйте установку через защищённое подключение и сравните время.

Коротко

  • Прочитайте код ошибки: ETIMEDOUT и ECONNRESET указывают на сеть, EINTEGRITY на кэш, ошибки сертификатов на прокси.
  • Проверьте npm config get registry и забытые файлы .npmrc.
  • Поднимите fetch-retries и паузы между повторами, снизьте maxsockets.
  • Исключите IPv6 через --dns-result-order=ipv4first.
  • Корпоративный сертификат добавляйте через cafile, а не отключайте проверку.
  • В CI используйте npm ci, кэш ~/.npm и --prefer-offline.
  • Если зависает уже после загрузки, проверьте --ignore-scripts: возможно, тормозит postinstall пакета.

Стабильный канал для работы

Один ключ, 20 стран, до 5 устройств на Standard. Возврат в течение 7 дней.

Все тарифы