Follow-up to #12158. That PR fixes the lockfile overrides metadata going stale after pnpm update bumps a catalog. This issue tracks a deeper case the metadata fix does not cover.
Problem
When an override references a catalog (overrides: { 'parent>child': 'catalog:' }) and the override is active (it forces a dependency that is actually in the resolved graph), a pnpm update that bumps the catalog applies the old override value to the graph. The resolution readPackageHook is built from opts.parsedOverrides, which is resolved once against the pre-update catalog in installing/deps-installer/src/install/extendInstallOptions.ts. updatedCatalogs is only known after resolveDependencies, so the resolved snapshots keep the pre-update version.
With #12158 applied (which fixes lockfile.overrides metadata), the result is a lockfile that records an override the graph does not honor:
after `pnpm update --latest` (catalog @pnpm.e2e/foo 100.0.0 -> latest 100.1.0):
catalogs.default['@pnpm.e2e/foo'] : { specifier: 100.1.0, version: 100.1.0 }
overrides['@pnpm.e2e/foobar>@pnpm.e2e/foo'] : 100.1.0 # fixed metadata (#12158)
snapshots['@pnpm.e2e/foobar@100.0.0'].dependencies.foo : 100.0.0 # STALE graph
foo snapshots present : 100.0.0 AND 100.1.0
A fresh pnpm install (with the post-update catalog) resolves @pnpm.e2e/foobar's @pnpm.e2e/foo to 100.1.0, so the pnpm update result diverges from a clean resolution. pnpm install --frozen-lockfile passes (the metadata is now consistent) but silently installs the old version for that transitive dependency. Without #12158 this case surfaced loudly as ERR_PNPM_LOCKFILE_CONFIG_MISMATCH; the metadata fix removes that error while the graph is still stale.
Failing test
Drop into installing/deps-installer/test/catalogs.ts (inside describe('update')):
test('an active catalog-backed override on a transitive dep stays consistent with the graph after update', async () => {
await addDistTag({ package: '@pnpm.e2e/foo', version: '100.1.0', distTag: 'latest' })
const { options, projects, readLockfile } = preparePackagesAndReturnObjects([{
name: 'project1',
dependencies: { '@pnpm.e2e/foo': 'catalog:', '@pnpm.e2e/foobar': '100.0.0' },
}])
const mutateOpts = {
...options,
lockfileOnly: true,
catalogs: { default: { '@pnpm.e2e/foo': '100.0.0' } },
overrides: { '@pnpm.e2e/foobar>@pnpm.e2e/foo': 'catalog:' },
}
await mutateModules(installProjects(projects), mutateOpts)
await addDependenciesToPackage(
projects['project1' as ProjectId],
['@pnpm.e2e/foo'],
{ ...mutateOpts, dir: path.join(options.lockfileDir, 'project1'), update: true, updateToLatest: true })
const lf = readLockfile()
expect(lf.catalogs.default).toEqual({ '@pnpm.e2e/foo': { specifier: '100.1.0', version: '100.1.0' } })
expect(lf.overrides).toEqual({ '@pnpm.e2e/foobar>@pnpm.e2e/foo': '100.1.0' })
// Fails today: @pnpm.e2e/foobar's @pnpm.e2e/foo is still 100.0.0.
expect(lf.snapshots['@pnpm.e2e/foobar@100.0.0'].dependencies?.['@pnpm.e2e/foo']).toBe('100.1.0')
})
Likely fix direction
Resolution needs to apply overrides using the updated catalog. Options:
- Re-resolve when an override references a catalog entry that
updatedCatalogs bumped (a second pass, only when needed), or
- Pre-compute the catalog
--latest bumps before resolution so the readPackageHook / parsedOverrides are built from the updated catalog and a single pass is correct.
Related: #12158 (metadata fix for the common case).
Follow-up to #12158. That PR fixes the lockfile
overridesmetadata going stale afterpnpm updatebumps a catalog. This issue tracks a deeper case the metadata fix does not cover.Problem
When an override references a catalog (
overrides: { 'parent>child': 'catalog:' }) and the override is active (it forces a dependency that is actually in the resolved graph), apnpm updatethat bumps the catalog applies the old override value to the graph. The resolutionreadPackageHookis built fromopts.parsedOverrides, which is resolved once against the pre-update catalog ininstalling/deps-installer/src/install/extendInstallOptions.ts.updatedCatalogsis only known afterresolveDependencies, so the resolved snapshots keep the pre-update version.With #12158 applied (which fixes
lockfile.overridesmetadata), the result is a lockfile that records an override the graph does not honor:A fresh
pnpm install(with the post-update catalog) resolves@pnpm.e2e/foobar's@pnpm.e2e/footo100.1.0, so thepnpm updateresult diverges from a clean resolution.pnpm install --frozen-lockfilepasses (the metadata is now consistent) but silently installs the old version for that transitive dependency. Without #12158 this case surfaced loudly asERR_PNPM_LOCKFILE_CONFIG_MISMATCH; the metadata fix removes that error while the graph is still stale.Failing test
Drop into
installing/deps-installer/test/catalogs.ts(insidedescribe('update')):Likely fix direction
Resolution needs to apply overrides using the updated catalog. Options:
updatedCatalogsbumped (a second pass, only when needed), or--latestbumps before resolution so thereadPackageHook/parsedOverridesare built from the updated catalog and a single pass is correct.Related: #12158 (metadata fix for the common case).