npm couldn't reach the registry (ENOTFOUND, ECONNREFUSED, ETIMEDOUT) or the request failed mid-transfer (EINTEGRITY after corrupt cache). Network layer first, cache second — and pinned registries/mirrors for CI determinism.
CI runners behind NATs with DNS flakiness, corporate proxies requiring HTTPS_PROXY, or IPv6-preferring runners with broken v6. curl https://registry.npmjs.org/ from the same environment is the baseline test.
A timed-out mid-tarball download leaves partial artifacts; subsequent installs verify integrity against them and fail with EINTEGRITY. npm cache clean --force (or just verify) resets it.
curl -sI --max-time 10 https://registry.npmjs.org/ | head -1 ; npm config get registry
npm config set proxy http://proxy:port ; npm config set https-proxy http://proxy:port # or env: HTTPS_PROXY
npm cache clean --force # then reinstall; integrity errors mid-transfer need this
# npm ci --prefer-offline --no-audit --fetch-retries=5 ; plus a job-level retry for the network class
npm ci (from a clean lockfile) is both faster and more deterministic than install in CI — the network surface per run is smaller and the resolution fixed. EINTEGRITY after a network blip is cache corruption, not tampering: clean and retry. Genuine integrity mismatches against the lockfile reproduce deterministically — that's the distinguishing test.
Different network egress (NAT, proxy, DNS) plus colder caches: CI refetches everything each run, multiplying the exposure to any registry hiccup. prefer-offline with a warm local cache cuts that surface.
A self-controlled mirror/registry proxy (Verdaccio, or a cloud mirror) helps with rate/flakiness and keeps private packages in one place. Pin it explicitly in CI config (NPM_CONFIG_REGISTRY) so it's visible, not ambient.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.