mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
Starting `pi` from a directory that has been deleted crashed with an uncaught Node `ENOENT ... uv_cwd` stack trace. This also happened for `--version` and `--help`. The cause is the unguarded `process.cwd()` call in `main()` (`packages/coding-agent/src/main.ts`). `main()` now catches `ENOENT` from that call, prints one line telling the user to change to an existing directory, and exits with code 1. Other errors are rethrown unchanged. Argument handling is otherwise unchanged: `--version` still needs a valid cwd, but it now gets the readable error instead of a crash. **Testing** - Added `test/deleted-cwd.test.ts`. It stubs `process.cwd()` to throw ENOENT and checks that `main()` prints the message and exits with code 1. It also checks that a non-ENOENT error is rethrown. The first test fails without the change and passes with it. - `npm run check` passes. - Manual check with the built CLI. Before, all three commands below printed the `uv_cwd` stack trace. After, each prints `Error: The current working directory no longer exists. Change to an existing directory and try again.` and exits 1: ```sh d=$(mktemp -d); cd "$d"; rmdir "$d" pi -ne --version; pi -ne --help; pi -ne ``` Fixes #11509 Requested by @badlogic Co-authored-by: triagent <triagent@localhost>
35 lines
1.3 KiB
TypeScript
35 lines
1.3 KiB
TypeScript
import { afterEach, describe, expect, test, vi } from "vitest";
|
|
import { main } from "../src/main.ts";
|
|
|
|
// Regression test for https://github.com/earendil-works/pi/issues/11509
|
|
describe("startup in a deleted working directory", () => {
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
test("prints an actionable error and exits 1 instead of throwing", async () => {
|
|
vi.spyOn(process, "cwd").mockImplementation(() => {
|
|
throw Object.assign(new Error("ENOENT: no such file or directory, uv_cwd"), {
|
|
code: "ENOENT",
|
|
syscall: "uv_cwd",
|
|
});
|
|
});
|
|
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
const exitSpy = vi.spyOn(process, "exit").mockImplementation(((code?: number) => {
|
|
throw new Error(`process.exit(${code})`);
|
|
}) as typeof process.exit);
|
|
|
|
await expect(main(["--no-extensions", "--version"])).rejects.toThrow("process.exit(1)");
|
|
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
const stderr = errorSpy.mock.calls.map(([message]) => String(message)).join("\n");
|
|
expect(stderr).toContain("The current working directory no longer exists");
|
|
});
|
|
|
|
test("rethrows unrelated cwd errors", async () => {
|
|
vi.spyOn(process, "cwd").mockImplementation(() => {
|
|
throw Object.assign(new Error("EACCES"), { code: "EACCES" });
|
|
});
|
|
|
|
await expect(main(["--no-extensions", "--version"])).rejects.toThrow("EACCES");
|
|
});
|
|
});
|