Conversation
A package `extends` specifier was resolved through node_modules but the
resulting path was never canonicalized, so a nested `extends` inside that
package was looked up from the symlink location. Under pnpm,
`node_modules/pkg` points into `node_modules/.pnpm/pkg@x/node_modules/pkg`,
so the lookup walked up to the project's root `node_modules`, where the
package's own dependencies do not exist:
× Tsconfig not found @tsconfig/node22/tsconfig.json
`tsc` resolves the same chain because it looks up module-resolved configs
through their real path. Apply `load_realpath` to the resolved config,
honoring `options.symlinks`, so nested `extends` resolve from the real
directory. Relative and absolute specifiers are unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Issue: web-infra-dev#15717
Contributor
|
@stormslowly PTAL |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Closes #15717.
When
resolve.tsConfigpoints at a config whoseextendschain passes througha package in
node_modules, and that package is a symlink (the normal pnpmlayout), the build fails:
The package
extendsspecifier is resolved throughnode_modules, but theresulting path was never canonicalized. The nested
extendsinside thatpackage was therefore looked up from the symlink location
(
<root>/node_modules/shared-config/), which walks up to the project's rootnode_modules, where the package's own dependencies do not exist — under pnpmthey live next to the real package directory in
node_modules/.pnpm/shared-config@…/node_modules/.tscresolves the same chain without complaint, since it looks upmodule-resolved configs through their real path. The same tree materialized
without a symlink (npm-style) also builds fine today, confirming the problem is
symlink-specific.
This is easy to hit unintentionally: any monorepo shipping a shared base
tsconfig as a package that itself extends
@tsconfig/*breaks under pnpm. Italso surfaces very indirectly through Rstest, which sets
resolve.tsConfigautomatically and swallows the resolver error.
Changes
Apply the existing
load_realpathto the config resolved for a bareextendsspecifier, so nested
extends(and relativeextendswithin that package)resolve from its real directory.
options.symlinksis honored, sosymlinks: falsekeeps the previous behavior. Relative and absoluteextendsspecifiers are untouched —
tsconly resolves module-resolved configs throughthe real path.
Regression test: a pnpm-style fixture where
node_modules/shared-configis asymlink into a store directory holding its
@tsconfig/basedependency next toit, absent from the project's own
node_modules. Without the fix the testfails with exactly
TsconfigNotFound("@tsconfig/base/tsconfig.json"). Thesymlink is created at test runtime (skipped when unprivileged on Windows),
matching the existing symlink test.
🤖 Generated with Claude Code