Operations 9 min read

When npm install Fails: npm ci, --legacy-peer-deps & --force Explained

Developers often struggle with choosing the right npm command for CI/CD pipelines, so this guide compares npm install and npm ci, explains version specifiers, and details how --legacy-peer-deps and --force can resolve dependency conflicts, registry issues, and build failures.

Code Mala Tang
Code Mala Tang
Code Mala Tang
When npm install Fails: npm ci, --legacy-peer-deps & --force Explained

Recently while adjusting CI/CD pipelines I organized the differences between npm install and npm ci , as well as the extra options --legacy-peer-deps and --force .

Why is this still a topic worth discussing?

In the past few months developers have struggled to find the correct command for installing dependencies.

Developers often ask the following questions:

Why did the CI/CD pipeline suddenly stop working? We only wanted to fix a bug. Two weeks ago everything was fine, now the pipeline fails.
We ran npm install and now we get a type error. What did we do wrong?
npm install failed due to dependency conflicts. We added --legacy-peer-deps , but now some dependencies are missing during the build. Why?
We changed the registry address in .npmrc , but each time we run npm install the old registry address is added to package-lock.json . Why?

npm install vs npm ci

Dependency versions are often listed with a caret (^) or tilde (~). With these specifiers npm installs the latest version that satisfies the range rather than an exact version.

~version : "approximately equivalent" (e.g., ~1.2.3 means >=1.2.3 <1.3.0)

^version : "compatible with" (e.g., ^1.2.3 means >=1.2.3 <2.0.0)

npm install

In short, npm install downloads and installs the latest dependencies listed in package.json and their sub‑dependencies, adds them to the local node_modules folder, caches the packages in the OS cache, and records the dependency tree in package-lock.json . Deleting node_modules does not force a full re‑download because npm will first look in the cache.

npm ci

Unlike npm install , npm ci uses package-lock.json and installs exactly the dependency tree recorded there. As long as the lock file is unchanged, each run produces identical installations.

--legacy-peer-deps and --force

Dependency conflicts occur when two or more packages require different versions of the same sub‑package.

What is a dependency conflict? If package A needs version 2.0.0 and package B needs version 1.0.0, npm cannot satisfy both simultaneously.

Using --legacy-peer-deps tells npm to ignore peer‑dependency conflicts and skip them, which usually resolves the conflict but may leave some packages missing.

How to apply this option? Add it to npm’s config or pass it directly on the command line.

<code>npm config set legacy-peer-deps=true
npm ci</code>

The --force flag, on the other hand, does not skip dependencies; it forces npm to install all versions, which can bloat node_modules and is rarely desired.

<code>npm install --force</code>

In summary, when facing a dependency conflict, --legacy-peer-deps is usually preferred; use --force only when missing dependencies require it.

Installing dependencies from scratch

Sometimes developers need to delete all local dependencies and reinstall, for example after changing a registry URL.

<code>rm -rf node_modules

npm cache clean --force
npm install --force</code>

Setting the correct registry

The registry URL is configured in the user’s .npmrc file. Only one registry can be set globally, but scoped registries allow multiple sources.

<code>registry=https:

@test:registry=http:</code>

FAQ

Below are common questions from the past months and their solutions.

Why did the CI/CD pipeline suddenly stop working? We only wanted to fix a bug. Two weeks ago everything was fine, now the pipeline fails.

The pipeline was using npm install instead of npm ci . Because the registry updates infrequently, newer packages were installed, overwriting package-lock.json and causing type errors. Always use npm ci in CI/CD.

We ran npm install and now we get a type error. What did we do wrong?

The same issue as above: a newer version of a dependency introduced a breaking change. The fix is to run npm ci to lock versions.

npm install failed due to dependency conflicts. We added --legacy-peer-deps , but now some dependencies are missing during the build. Why?

Skipped dependencies caused the missing packages. Use npm ci --force to reinstall everything.

We changed the registry address in .npmrc , but each time we run npm install the old registry address is added to package-lock.json . Why?

The old packages are still cached locally. Clean the cache and reinstall:

<code>npm cache clean --force</code>

Summary

Use npm ci in CI/CD pipelines; otherwise installing newer dependency versions may cause build failures.

ci/cddependency-managementnodejsnpmpackage-lockforcelegacy-peer-deps
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.