Compare commits

...

7 Commits

Author SHA1 Message Date
Jarred Sumner
9d281c5919 Merge branch 'main' into claude/fix-missing-file-dep-error-message 2026-01-23 20:24:27 -08:00
Claude Bot
e13a0687e5 fix(test): update 26337 test to match new error message format
The error message format changed from "error occurred while resolving"
to "failed to resolve" - update test to match.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 23:27:13 +00:00
Claude Bot
02daea84e0 Merge main into claude/fix-missing-file-dep-error-message 2026-01-23 23:21:34 +00:00
Claude Bot
cde91147e0 trigger CI rebuild 2026-01-23 22:54:20 +00:00
Claude Bot
b9bd652a6b fix(test): update bun-add test to expect new file: dependency error message
The error message format changed from "MissingPackageJSON" to
"Could not find package.json for {path} dependency" - update the
test expectation to match.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 22:21:29 +00:00
Jarred Sumner
01602c9223 Merge branch 'main' into claude/fix-missing-file-dep-error-message 2026-01-21 18:42:04 -08:00
Claude Bot
c6d4fb512e fix(install): improve error message for missing file: dependency path
When a file: dependency's target path doesn't exist (e.g., due to a
stale lockfile), Bun was showing a misleading "Bun could not find a
package.json file to install from" error that suggested running
"bun init".

The actual issue was that the folder path for the file: dependency
didn't exist. This commit adds specific handling for MissingPackageJSON
errors from file: dependency resolution to show a more helpful error
message that includes the actual path that was not found.

Also adds a defensive check for version.tag to avoid undefined behavior
if a non-folder tag ever produces MissingPackageJSON.

Fixes #26338

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 14:31:00 +00:00
4 changed files with 96 additions and 4 deletions

View File

@@ -621,6 +621,40 @@ pub fn enqueueDependencyWithMainAndSuccessFn(
}
return;
},
error.MissingPackageJSON => {
if (dependency.behavior.isRequired()) {
if (failFn) |fail| {
fail(
this,
dependency,
id,
err,
);
} else if (version.tag == .folder) {
this.log.addErrorFmt(
null,
logger.Loc.Empty,
this.allocator,
"Could not find package.json for \"file:{s}\" dependency \"{s}\"",
.{
this.lockfile.str(&version.value.folder),
this.lockfile.str(&name),
},
) catch unreachable;
} else {
this.log.addErrorFmt(
null,
logger.Loc.Empty,
this.allocator,
"Could not find package.json for dependency \"{s}\"",
.{
this.lockfile.str(&name),
},
) catch unreachable;
}
}
return;
},
else => {
if (failFn) |fail| {
fail(

View File

@@ -111,8 +111,8 @@ it("should reject missing package", async () => {
env,
});
const err = await stderr.text();
expect(err).toContain("error: MissingPackageJSON");
expect(err).toContain(`note: error occurred while resolving file:${add_path}`);
expect(err).toContain(`error: Could not find package.json for "file:${add_path}" dependency`);
expect(err).toContain("failed to resolve");
const out = await stdout.text();
expect(out).toEqual(expect.stringContaining("bun add v1."));

View File

@@ -67,10 +67,11 @@ describe("issue #26337 - missing file: dependency error should show dependency n
failProc.exited,
]);
// The error output should mention the dependency name
// The error output should mention the dependency name and path
const output = stdout + stderr;
expect(output).toContain("@scope/dep");
expect(output).toContain("error occurred while resolving");
expect(output).toContain("file:./nonexistent/path");
expect(output).toContain("failed to resolve");
// The install should fail
expect(exitCode).toBe(1);

View File

@@ -0,0 +1,57 @@
// https://github.com/oven-sh/bun/issues/26338
// Test that when a lockfile references a stale file: dependency path,
// the error message correctly identifies the missing dependency path
// instead of showing "Bun could not find a package.json file to install from"
import { expect, test } from "bun:test";
import { bunEnv, bunExe, tempDir } from "harness";
test("shows informative error for missing file: dependency path", async () => {
// Create a directory structure where:
// - package.json references a path that doesn't exist
// - bun.lock references a different (also non-existent) path
// This simulates a stale lockfile scenario
using dir = tempDir("missing-file-dep", {
"package.json": JSON.stringify({
name: "app",
version: "1.0.0",
dependencies: {
dep: "file:../packages/@scope/dep",
},
}),
"bun.lock": JSON.stringify({
lockfileVersion: 1,
configVersion: 1,
workspaces: {
"": {
name: "app",
dependencies: {
dep: "file:../dep",
},
},
},
packages: {
dep: ["dep@file:../dep", {}],
},
}),
});
await using proc = Bun.spawn({
cmd: [bunExe(), "install"],
cwd: String(dir),
env: bunEnv,
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
// The error should mention the file: path, not a generic "package.json not found" message
expect(stderr).toContain("file:../packages/@scope/dep");
// Check that the dependency name "dep" appears as a quoted token (not just as part of "dependency")
expect(stderr).toMatch(/"dep"/);
expect(stderr).not.toContain("Bun could not find a package.json file to install from");
expect(stderr).not.toContain('Run "bun init" to initialize a project');
expect(exitCode).not.toBe(0);
});