Two major versions of the same package installed simultaneously means two copies of that code running in your application. For React, this causes hooks to fail silently or crash at runtime because each copy maintains its own internal state. For validation libraries, it means validators from one version cannot accept instances created by the other. The ISO 25010 maintainability characteristic is directly degraded: duplicate packages make the dependency graph non-deterministic from a debugging standpoint and inflate install size without adding functionality. Duplicate packages most commonly appear when you upgrade a direct dependency but a transitive parent still pins the old major — the resolution is visible in the lock file but invisible at the source code level.
Low because duplicate major versions rarely introduce security vulnerabilities directly, but they cause subtle runtime failures and inflate bundle size in ways that are difficult to diagnose without explicit dependency graph inspection.
Diagnose which package requires the old version:
npm ls react
If the old version comes from a third-party dependency you cannot upgrade immediately, force resolution using overrides:
// package.json
"overrides": {
"react": "^18.0.0"
}
Test thoroughly after applying the override — forcing a newer major can break packages that genuinely rely on the older API. The correct long-term fix is upgrading or replacing the package that pins the old version.
ID: dependency-supply-chain.optimization.no-duplicate-packages
Severity: low
What to look for: Examine the lock file for the same package name installed at multiple different versions. In package-lock.json, look for packages that appear in multiple node_modules/.pnp.cjs paths or as multiple entries in the packages section. In pnpm-lock.yaml, look for duplicate package entries. Common culprits: react and react-dom at different versions, multiple versions of @babel/*, multiple versions of jest-*, duplicate tslib versions. Two different major versions of the same package installed simultaneously inflates bundle size and can cause subtle runtime errors (two React instances, two different validator instances, etc.). Count all instances found and enumerate each.
Pass criteria: No production packages (those used at runtime) are installed at more than one major version simultaneously. At least 1 implementation must be confirmed.
Fail criteria: A production package is installed at two or more conflicting major versions in the same project.
Skip (N/A) when: No lock file detected.
Cross-reference: The outdated-major-versions check in Maintenance verifies that deduplication does not require major version upgrades with breaking changes.
Detail on fail: "react@16.14.0 and react@18.3.1 are both installed in the dependency tree — this is likely from a third-party package that hasn't been updated to React 18"
Remediation: Duplicate packages at different major versions usually indicate that one of your dependencies requires an older version of a package that you've also upgraded directly. This is called a version conflict.
To diagnose:
npm ls react # shows which package requires which version
To resolve:
overrides to force all resolutions to the newer version:
// package.json
"overrides": {
"react": "^18.0.0"
}
Note: overrides can break packages that genuinely require the older version — test thoroughly.