Introduction

The npm ci command performs a clean install based strictly on package-lock.json, verifying the integrity checksum of every downloaded package. When a package's downloaded tarball does not match the integrity hash stored in package-lock.json, npm aborts with EINVAL: invalid argument, read or Integrity checksum failed. This error commonly occurs when the lock file was generated on a different registry (like a private npm proxy), when a package was republished with different content (a rare but serious security event), or when the npm cache is corrupted.

Symptoms

bash
npm ERR! code EINTEGRITY
npm ERR! sha512-abc123... integrity checksum failed when using sha512: wanted sha512-abc123... but got sha512-def456... (45678 bytes)

Or:

bash
npm ERR! sha1-xyz789 integrity checksum failed when using sha1:
wanted sha1-xyz789 but got sha1-abc123. (12345 bytes)

Or with registry proxy:

bash
npm ERR! 404 Not Found - GET https://registry.npmjs.org/my-private-package/-/my-private-package-1.2.3.tgz
npm ERR! notarget No matching version found for my-private-package@1.2.3

Common Causes

  • Corrupted npm cache: Cached tarball differs from what the registry now serves
  • Package-lock.json generated on different registry: Private registry hashes differ from public npm
  • Package republished: A maintainer unpublished and republished a version with different content
  • Corporate proxy modifies packages: MITM proxy alters package contents, changing the hash
  • Outdated npm version: Older npm versions calculate integrity differently
  • Git-based dependencies changed: A git dependency's commit was force-pushed with different content

Step-by-Step Fix

Step 1: Clear npm cache and retry

```bash # Clear the cache forcefully npm cache clean --force

# Verify cache integrity npm cache verify

# Retry the install npm ci ```

Step 2: Regenerate package-lock.json

If the cache clean does not help, the lock file may be out of sync:

```bash # Delete the lock file and node_modules rm -rf node_modules package-lock.json

# Fresh install (generates new lock file) npm install

# Commit the new lock file git add package-lock.json git commit -m "Regenerate package-lock.json"

# Now npm ci should work npm ci ```

Step 3: Configure registry correctly

```bash # Set the correct registry npm config set registry https://registry.npmjs.org/

# For private packages, use .npmrc cat > .npmrc << 'EOF' registry=https://registry.npmjs.org/ @myorg:registry=https://npm.pkg.github.com/ //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} EOF

# Verify registry configuration npm config get registry ```

Step 4: Handle corporate proxy checksums

If behind a corporate proxy that modifies packages:

```bash # Disable integrity check (not recommended for security) npm ci --ignore-scripts

# Or configure npm to use the corporate registry npm config set registry https://npm-proxy.company.com/ npm config set cafile /path/to/corporate-ca.pem ```

Prevention

  • Always commit package-lock.json to version control
  • Use npm ci in CI/CD pipelines, not npm install
  • Pin exact versions in package.json (not ranges) for production dependencies
  • Run npm audit regularly to detect compromised packages
  • Add a CI step that verifies npm ci succeeds with the committed lock file
  • Use npm cache verify as part of your deployment health checks
  • Configure .npmrc in the repository root for consistent registry settings across the team