Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
04e9c2eb9d fix(install): set non-zero exit code on tarball download failures
When a tarball download fails (connection error or HTTP error), the
error was logged but `any_failed_to_install` was not set to true. This
caused `bun install` to exit with code 0 despite errors being printed.

Now sets `any_failed_to_install = true` when a required network task
fails during tarball download, ensuring the process exits with code 1.

Fixes #2766

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 01:02:58 +00:00
2 changed files with 88 additions and 0 deletions

View File

@@ -394,6 +394,7 @@ pub fn runTasks(
extract.resolution.fmt(manager.lockfile.buffers.string_bytes.items, .auto),
},
) catch |e| bun.handleOom(e);
manager.any_failed_to_install = true;
} else {
manager.log.addWarningFmt(
null,
@@ -458,6 +459,7 @@ pub fn runTasks(
response.status_code,
},
) catch |err| bun.handleOom(err);
manager.any_failed_to_install = true;
} else {
manager.log.addWarningFmt(
null,

View File

@@ -0,0 +1,86 @@
import type { Server } from "bun";
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import { bunEnv, bunExe, tempDir } from "harness";
/**
* Test for GitHub issue #2766
* When a tarball download fails (HTTP error or connection error), bun install
* should exit with a non-zero exit code.
*/
describe("issue #2766 - tarball download failures should cause non-zero exit code", () => {
let mockRegistry: Server;
let mockRegistryUrl: string;
beforeEach(async () => {
mockRegistry = Bun.serve({
port: 0,
async fetch(req) {
const url = new URL(req.url);
// Package metadata endpoint - always succeeds
if (url.pathname === "/test-package-404") {
return new Response(
JSON.stringify({
name: "test-package-404",
"dist-tags": { latest: "1.0.0" },
versions: {
"1.0.0": {
name: "test-package-404",
version: "1.0.0",
dist: {
tarball: `${mockRegistryUrl}/test-package-404/-/test-package-404-1.0.0.tgz`,
integrity: "sha512-invalidintegrity==",
},
},
},
}),
{ headers: { "Content-Type": "application/json" } },
);
}
// Tarball endpoint - return 404 to simulate download failure
if (url.pathname.endsWith(".tgz")) {
return new Response("Not Found", { status: 404 });
}
return new Response("Not found", { status: 404 });
},
});
mockRegistryUrl = `http://localhost:${mockRegistry.port}`;
});
afterEach(() => {
mockRegistry?.stop();
});
test("bun install exits with non-zero code when tarball download returns 404", async () => {
using dir = tempDir("issue-2766", {
"package.json": JSON.stringify({
name: "test-project",
dependencies: {
"test-package-404": "1.0.0",
},
}),
"bunfig.toml": `
[install]
registry = "${mockRegistryUrl}/"
`,
});
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]);
// Should have error output about the failed tarball
expect(stderr).toContain("404");
// Must exit with non-zero code
expect(exitCode).not.toBe(0);
});
});