npm install зависает или падает по таймауту: чек-лист
Зависший npm install выглядит одинаково, а причины разные: реестр, DNS, IPv6, прокси, повреждённый кэш. Идите по списку сверху вниз и не меняйте всё сразу, иначе не поймёте, что помогло.
Что означают ошибки
В новых версиях npm строки ошибок начинаются с npm error, в старых с npm ERR!. Коды при этом те же.
| Код | Причина |
|---|---|
| ETIMEDOUT | Соединение с реестром не установилось за отведённое время. Сеть, прокси или межсетевой экран |
| ECONNRESET | Соединение оборвали посреди передачи. Нестабильный канал или прокси, который рвёт долгие запросы |
| ERR_SOCKET_TIMEOUT | Соединение есть, но данные перестали приходить |
| EAI_AGAIN | Временный сбой DNS: имя реестра не разрешилось |
| ENOTFOUND | DNS не знает такого имени. Часто это опечатка в адресе реестра в .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 doctornpm 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:3128npm также читает переменные 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пакета.