Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
020cef4b98 fix(resolver): show warning when tsconfig extends non-existent file
Previously, when a tsconfig.json's "extends" field referenced a non-existent
file, Bun silently ignored it (only logging at debug level). This made it
difficult for users to diagnose configuration issues.

Now, a warning is shown when the extended config file cannot be found,
similar to TypeScript's behavior. Warnings are suppressed for tsconfig files
inside node_modules to avoid noise from third-party packages.

Fixes #2804

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 01:06:38 +00:00
2 changed files with 59 additions and 6 deletions

View File

@@ -4203,12 +4203,19 @@ pub const Resolver = struct {
const ts_dir_name = Dirname.dirname(current.abs_path);
const abs_path = ResolvePath.joinAbsStringBuf(ts_dir_name, bufs(.tsconfig_path_abs), &[_]string{ ts_dir_name, current.extends }, .auto);
const parent_config_maybe = r.parseTSConfig(abs_path, bun.invalid_fd) catch |err| {
r.log.addDebugFmt(null, logger.Loc.Empty, r.allocator, "{s} loading tsconfig.json extends {f}", .{
@errorName(err),
bun.fmt.QuotedFormatter{
.text = abs_path,
},
}) catch {};
// Only show warnings for tsconfig files outside of node_modules
if (!info.isInsideNodeModules()) {
if (err == error.ENOENT or err == error.FileNotFound) {
r.log.addWarningFmtLineCol(current.abs_path, 0, 0, r.allocator, "Cannot find base config file {f}", .{
bun.fmt.QuotedFormatter{ .text = current.extends },
}) catch {};
} else if (err != error.ParseErrorAlreadyLogged and err != error.IsDir and err != error.EISDIR) {
r.log.addWarningFmtLineCol(current.abs_path, 0, 0, r.allocator, "Cannot read base config file {f}: {s}", .{
bun.fmt.QuotedFormatter{ .text = current.extends },
@errorName(err),
}) catch {};
}
}
break;
};
if (parent_config_maybe) |parent_config| {

View File

@@ -0,0 +1,46 @@
import { expect, test } from "bun:test";
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
test("tsconfig extends non-existent file shows warning", () => {
const dir = tempDirWithFiles("02804", {
"tsconfig.json": JSON.stringify({
extends: "./nonexistent-config.json",
compilerOptions: {
strict: true,
},
}),
"index.ts": `const x: string = "hello"; console.log(x);`,
});
const proc = Bun.spawnSync([bunExe(), "index.ts"], {
env: bunEnv,
cwd: dir,
stderr: "pipe",
stdout: "pipe",
});
const stderr = proc.stderr.toString("utf-8");
expect(stderr).toContain('Cannot find base config file "./nonexistent-config.json"');
expect(stderr).toContain("warn:");
});
test("tsconfig extends inside node_modules does not warn", () => {
const dir = tempDirWithFiles("02804-node-modules", {
"index.ts": `import "./node_modules/foo/index.js"; console.log("done");`,
"node_modules/foo/tsconfig.json": JSON.stringify({
extends: "./nonexistent-config.json",
}),
"node_modules/foo/index.js": `console.log("foo");`,
});
const proc = Bun.spawnSync([bunExe(), "index.ts"], {
env: bunEnv,
cwd: dir,
stderr: "pipe",
stdout: "pipe",
});
const stderr = proc.stderr.toString("utf-8");
// Should NOT show warning for files inside node_modules
expect(stderr).not.toContain("Cannot find base config file");
});