Skip to content

[Bug?]: pnp top level fallback causes issues when converting to a monorepo #6820

Open
@scytacki

Description

@scytacki

Self-service

  • I'd be willing to implement a fix

Describe the bug

When I moved a Yarn PnP flat repo to a monorepo with multiple workspaces, a few tools broke which were unexpected. This seems to be because these tools are using createRequire incorrectly. The tools seem to pass a file being processed as the filename argument to createRequire when they want to load a plugin. As long as the repository is flat then this works due to the top level fallback behavior of pnp. But if the package using the tool is moved into a workspace of a monorepo the tool will fail until its required plugins are added to the root package.json.

I realize this is the expected behavior. I just wanted to report that tools are making this mistake, and it is hard for end users to figure out what is going on.

I've found the best practice guidelines here: https://yarnpkg.com/advanced/rulebook
And the documentation about this top level fallback here: https://yarnpkg.com/advanced/pnp-spec#enableTopLevelFallback

Three improvements around this I can think of:

  • add an optional warning message when the fallback is used so it is easier to figure out which packages still need the fallback
  • when a dependency can't be resolved even with the fallback is enabled, add some text to the raised error about the fallback. Currently error only describes how the package doesn't declare a dependency on package it is trying to load. I'm proposing the message also said, "and the dependency can't be found in the fallback location." Unfortunately developers looking for a quick fix might just take advantage of this message and add packages to the top level, instead of helping the package do the right thing. But at least it will raise visibility about this fallback mechanism.
  • an enhanced error or debug mode which would print out messages about failed dependency resolutions along with this fallback info. This would be useful for packages which are hiding the actual error message returned when a dependency can't be resolved. A developer which realizes there is some dependency resolution problem would learn to turn on this mode to help them track down the problem faster.

A drastic solution would be to consider setting the default value of the fallback to none, so packages would be forced to deal with it or tell their users they need to change the fallback configuration.

One example is the ESLint import-x plugin: un-ts/eslint-plugin-import-x#381

Another tool which seems to also use createRequire incorrectly is the typescript support in Jest. I haven't tracked this down, but it seems to be behave the same way as the import-x plugin. In a flat repo with a ts-lib as a dependency it works. In a mono repo with the ts-lib in the workspace package.json Jest fails. The error message indicates it is trying to load ts-lib from a package that Jest is trying to transpile. If the ts-lib is added to the root package.json, the error goes away.

To reproduce

Here is a repo that exhibits this problem:
https://github.com/concord-consortium/test-eslint-import-x/tree/monorepo-typescript

The eslint-plugin-import-x package is eating the error returned by PnP, so only the 1st and 3rd bullets would be useful in this case.

Environment

System:
    OS: macOS 15.4.1
    CPU: (12) arm64 Apple M2 Max
  Binaries:
    Node: 20.17.0 - /private/var/folders/yb/wql4q1vx32zd36h0lnfngqvc0000gn/T/xfs-bf1faf1a/node
    Yarn: 4.9.2 - /private/var/folders/yb/wql4q1vx32zd36h0lnfngqvc0000gn/T/xfs-bf1faf1a/yarn
    npm: 10.8.2 - ~/.nvm/versions/node/v20.17.0/bin/npm

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions