🚀 Feature Request
In packages/playwright/src/transform/tsconfig-loader.ts, resolveConfigFile() has a fallback that retries unresolved extends/references paths against node_modules. The condition (referencedConfigFile.includes('/') && includes('.')) also matches ordinary relative paths, not just package specifiers. Since path.join collapses ../ segments, a typo'd relative reference like "../shared/tsconfig.base.json" hits this branch anyway, produces a second path that also doesn't exist, and innerLoadTsConfig's existsSync check then just returns an empty config — so a broken extends or references entry fails completely silently instead of erroring.
There's already a TODO on this exact line ("I don't see how this makes sense, delete in the next minor release"), which suggests this confused a previous maintainer too.
Feature ask: surface a clear error when a referenced or extended tsconfig path can't be resolved by either the relative or node_modules lookup, instead of silently defaulting to an empty config.
One related question worth settling first: playwright.dev/docs/test-typescript lists only allowJs, baseUrl, paths, and references as supported tsconfig options — extends isn't mentioned, but the code fully resolves extends chains. If extends support is intentional but undocumented, the fix should keep it working and just make failures loud. If it's legacy and unowned, maybe it should go away entirely along with this fallback. Happy to send a PR either way once that's clarified.
Example
Given a tests/tsconfig.json with:
"extends": "./tsconfig.bas.json" (typo :file doesn't exist)
Today: Playwright loads silently, the typo'd extends is ignored, and the paths/baseUrl the test author expected to inherit never get applied — with no warning, making it confusing to debug.
With this change: config loading would throw something like
Failed to resolve "extends" path "./tsconfig.bas.json" referenced from tests/tsconfig.json
at config-load time, pointing straight at the typo instead of leaving the misconfiguration silent.
Motivation
This bites people in a way that's hard to trace back to the actual cause. If you reorganize a monorepo, rename a shared tsconfig, or just typo a path in extends/references, Playwright doesn't error : it silently falls back to an empty config. The visible symptoms show up somewhere else entirely: path mappings stop resolving, baseUrl-relative imports break, or strict-mode settings you thought were inherited just aren't applied. None of that points back to "your tsconfig reference is broken," so people lose time debugging the symptom instead of the cause.
This is especially painful in CI, where there's no interactive session to poke around in — a silently-empty config just produces confusing downstream test failures with no actionable error message anywhere in the log.
Most config-loading systems (tsc itself included) treat an unresolvable extends as a hard error rather than a silent no-op, so failing loudly here would bring tsconfig-loader in line with the behavior people already expect from TypeScript tooling, and would turn a multi-hour debugging session into an error message that names the exact bad path on the first run.
🚀 Feature Request
In packages/playwright/src/transform/tsconfig-loader.ts, resolveConfigFile() has a fallback that retries unresolved extends/references paths against node_modules. The condition (referencedConfigFile.includes('/') && includes('.')) also matches ordinary relative paths, not just package specifiers. Since path.join collapses ../ segments, a typo'd relative reference like "../shared/tsconfig.base.json" hits this branch anyway, produces a second path that also doesn't exist, and innerLoadTsConfig's existsSync check then just returns an empty config — so a broken extends or references entry fails completely silently instead of erroring.
There's already a TODO on this exact line ("I don't see how this makes sense, delete in the next minor release"), which suggests this confused a previous maintainer too.
Feature ask: surface a clear error when a referenced or extended tsconfig path can't be resolved by either the relative or node_modules lookup, instead of silently defaulting to an empty config.
One related question worth settling first: playwright.dev/docs/test-typescript lists only allowJs, baseUrl, paths, and references as supported tsconfig options — extends isn't mentioned, but the code fully resolves extends chains. If extends support is intentional but undocumented, the fix should keep it working and just make failures loud. If it's legacy and unowned, maybe it should go away entirely along with this fallback. Happy to send a PR either way once that's clarified.
Example
Given a tests/tsconfig.json with:
"extends": "./tsconfig.bas.json" (typo :file doesn't exist)
Today: Playwright loads silently, the typo'd extends is ignored, and the paths/baseUrl the test author expected to inherit never get applied — with no warning, making it confusing to debug.
With this change: config loading would throw something like
Failed to resolve "extends" path "./tsconfig.bas.json" referenced from tests/tsconfig.json
at config-load time, pointing straight at the typo instead of leaving the misconfiguration silent.
Motivation
This bites people in a way that's hard to trace back to the actual cause. If you reorganize a monorepo, rename a shared tsconfig, or just typo a path in extends/references, Playwright doesn't error : it silently falls back to an empty config. The visible symptoms show up somewhere else entirely: path mappings stop resolving, baseUrl-relative imports break, or strict-mode settings you thought were inherited just aren't applied. None of that points back to "your tsconfig reference is broken," so people lose time debugging the symptom instead of the cause.
This is especially painful in CI, where there's no interactive session to poke around in — a silently-empty config just produces confusing downstream test failures with no actionable error message anywhere in the log.
Most config-loading systems (tsc itself included) treat an unresolvable extends as a hard error rather than a silent no-op, so failing loudly here would bring tsconfig-loader in line with the behavior people already expect from TypeScript tooling, and would turn a multi-hour debugging session into an error message that names the exact bad path on the first run.