pnpm icon indicating copy to clipboard operation
pnpm copied to clipboard

Can't use specifier for a snapshot dependency in the lock file

Open gabrielmfern opened this issue 1 year ago • 13 comments

Verify latest release

  • [X] I verified that the issue exists in the latest pnpm release

pnpm version

9.1.2

Which area(s) of pnpm are affected? (leave empty if unsure)

Dependencies resolver, Lockfile

Link to the code that reproduces this issue or a replay of the bug

https://github.com/gabrielmfern/pnpm-resolution-issue-repro

Reproduction steps

  1. Check that the resolution of @types/react for types-react-dom is an exact version not a specifier
  2. Try adding a specifier into the snapshot for types-react-dom by changing it to:
  [email protected]:
    dependencies:
      '@types/react': 
        specifier: npm:types-react@rc
        version: [email protected]
  1. Confirm that it errors when running pnpm install

Describe the Bug

I was specifically trying to upgrade the React's types package to React 19 by changing the dependencies with something like:

{
  "devDependencies": {
    "@types/react": "npm:types-react@rc",
    "@types/react-dom": "npm:types-react-dom@rc",
  }
}

But, since types-react-dom has @types/react as a dependency, I would expect pnpm to resolve into using types-react as @types/react instead of a published version of @types/react, but, it apparently resolves into using another resolved version of @types/react in my workspace.

After noticing this happening, I tried going through the lock file to see if I could manually solve the resolution of it, which was something like:

importers:
  project:
    devDependencies:
      '@types/react':
        specifier: npm:types-react@rc
        version: [email protected]
      '@types/react-dom':
        specifier: npm:types-react-dom@rc
        version: [email protected]
snapshots:
  [email protected]:
    dependencies:
      '@types/react': 18.2.47

And then I tried changing the snapshot to the following to fix the issue:

importers:
  project:
    devDependencies:
      '@types/react':
        specifier: npm:types-react@rc
        version: [email protected]
      '@types/react-dom':
        specifier: npm:types-react-dom@rc
        version: [email protected]
snapshots:
  [email protected]:
    dependencies:
-      '@types/react': 18.2.47
+      '@types/react':
+        specifier: npm:types-react@rc
+        version: [email protected]

And I was met with the following error:

 ERROR  ref.startsWith is not a function

pnpm: ref.startsWith is not a function
    at refsByPkgNames.reduce.depPaths (/corepack/pnpm/9.1.2/dist/pnpm.cjs:137562:17)
    at Array.reduce (<anonymous>)
    at parseDepRefs (/corepack/pnpm/9.1.2/dist/pnpm.cjs:137561:29)
    at pkgAllDeps (/corepack/pnpm/9.1.2/dist/pnpm.cjs:137530:83)
    at pickPkgsWithAllDeps (/corepack/pnpm/9.1.2/dist/pnpm.cjs:137485:7)
    at filterLockfileByImportersAndEngine (/corepack/pnpm/9.1.2/dist/pnpm.cjs:137453:52)
    at filterLockfileByEngine (/corepack/pnpm/9.1.2/dist/pnpm.cjs:137444:14)
    at headlessInstall (/corepack/pnpm/9.1.2/dist/pnpm.cjs:174676:74)
    at async _install (/corepack/pnpm/9.1.2/dist/pnpm.cjs:192101:33)
    at async mutateModules (/corepack/pnpm/9.1.2/dist/pnpm.cjs:191966:23)

Expected Behavior

I would expect that it either would work after changing the lock file, or it would be resolving it properly based on the current package instead of the version in the workspace or the latest version.

Which Node.js version are you using?

20.11.1

Which operating systems have you used?

  • [ ] macOS
  • [ ] Windows
  • [X] Linux

If your OS is a Linux based, which one it is? (Include the version if relevant)

Arch Linux

gabrielmfern avatar Jun 04 '24 16:06 gabrielmfern

Can't use specifier for a snapshot dependency in the lock file

This is not your real problem, your real problem is that you want to use types-react in place of @types/react, correct?

Is overrides sufficient?

{
  "pnpm": {
    "overrides": {
      "@types/react": "npm:types-react@rc"
    }
  }
}

KSXGitHub avatar Jun 04 '24 19:06 KSXGitHub

Hey @KSXGitHub

This is not your real problem, your real problem is that you want to use types-react in place of @types/react, correct?

Sort of, yes. More specifically, it is that the resolved dependency of @types/react for types-react-dom is not being resolved as types-react.

Is overrides sufficient?

I have tried overrides, they are enabled on the repro I made actually, but it doesn't make any difference.

My thinking, coming from someone unfamiliar with pnpm internals, is that pnpm can't resolve it from the override precisely because it can't use specifiers on snapshot dependencies.

gabrielmfern avatar Jun 04 '24 20:06 gabrielmfern

overrides should be at top-level package.json.

The documentation clearly states:

Note that the overrides field can only be set at the root of the project.

KSXGitHub avatar Jun 04 '24 21:06 KSXGitHub

Oh, didn't know that. Thanks for the heads-up. Still, though, it resolves to a set version instead of the specifier:

  [email protected]:
    dependencies:
      '@types/react': 18.3.3

gabrielmfern avatar Jun 06 '24 16:06 gabrielmfern

Still, though, it resolves to a set version instead of the specifier

I have cloned your repo and set pnpm.overrides then run pnpm install. This is the result:

lockfile screenshot

I suspect you set overrides instead of pnpm.overrides. You should double check. Is your overrides inside a pnpm object?

KSXGitHub avatar Jun 06 '24 16:06 KSXGitHub

You are right, I misconfigured it again, sorry for not reading the docs thoroughly enough on this, but, the issue still seems to persist.

Also, from the part of the lock file you shared, I still think I haven't got my issue across clearly enough though, so let me go through it again. types-react-dom has a dependency on @types/react, specifically it has "@types/react": "*". The problem, then, is that the version that pnpm is resolving for this specific dependency (18.3.3) is not the same as the override (npm:types-react@rc).

My initial thinking was that pnpm should resolve it from my own specified version for @types/react (which is npm:types-react@rc), but I guess that is out of pnpm's scope. This not working with the override still seems to me like an issue, though, wonder what you think about this. Let me know if I'm being clear enough.

Small note on when the issue happens

The issue doesn't actually seem to happen when you depend directly on types-react-dom. The snapshots section I've been mentioning then looks like:

  [email protected]:
    dependencies:
      '@types/react': [email protected]

Which I guess I can manually add in as a workaround. But this is what it is supposed to be resolved to when the proper override is configured.

gabrielmfern avatar Jun 06 '24 18:06 gabrielmfern

@gabrielmfern I think I get what you mean: You are referring to the fact that even though @types/react has been overridden, types-react-dom still depends on @types/react instead of types-react. As seen in the snapshot section of the lockfile:

snapshots:
  # ...

  [email protected]:
    dependencies:
      '@types/react': 18.3.3

I have inspect the problem and found that the problem is from with-react-19/package.json. You may change it to the following:

{
  "name": "with-react-19",
  "devDependencies": {
    "@types/react": "18.3.3",
    "@types/react-dom": "18.3.0"
  }
}

The snapshots in the lockfile should now be as you desired:


snapshots:

  [email protected]: {}

  [email protected]:
    dependencies:
      '@types/react': [email protected]

  [email protected]:
    dependencies:
      csstype: 3.1.3

KSXGitHub avatar Jun 06 '24 18:06 KSXGitHub

@zkochan I see that overrides doesn't affect dependencies of dependencies specified with npm: scheme. Is this intended behavior?

KSXGitHub avatar Jun 06 '24 18:06 KSXGitHub

Yeah, it works! That's interesting, but really unintuitive, why does this even work?

gabrielmfern avatar Jun 06 '24 18:06 gabrielmfern

@KSXGitHub probably not intended.

zkochan avatar Jun 06 '24 21:06 zkochan

It is interesting that I can't reproduce the bug with clean install.

KSXGitHub avatar Jun 07 '24 09:06 KSXGitHub

So the bug only appears if there was a lockfile from previous install (without pnpm.overrides). Removing the lockfile and run pnpm install again and it will work properly.

KSXGitHub avatar Jun 10 '24 16:06 KSXGitHub

Actually, both the lockfile and the node_modules directory have to be removed to workaround this bug.

Removing only the lockfile but not node_modules then run pnpm install would create a different lockfile from before setting overrides, but still not the same one as complete clean install. The complete clean install version is the most minimal.

KSXGitHub avatar Jun 10 '24 16:06 KSXGitHub